Non-static variable this when putting into a static map - java

I have a static HashMap to which I'm adding a new item like so:
public static void addSession(Session session) {
if(!map.containsKey(session)){
map.put(session, new SessionThread(session));
}
}
SessionThread is declared locally like so:
public class SessionThread implements Runnable {
That map.put line has a compile error of non-static variable this cannot be referenced from a static context. What is causing the error? this is not referenced anywhere in that method, let alone any non-static members. Everything is either static or in the scope of the method.
Entire class...
package me.scratchjava;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Queue;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.websocket.RemoteEndpoint;
import javax.websocket.Session;
/**
* A class for managing websocket threads.
* #author James Smyth <jimsmyth at datafascia.com>
*/
public class SessionManager {
private static HashMap<Session, SessionThread> map = new HashMap<>();
/**
* Called whenever a new websocket is opened.
* #param session
*/
public static void addSession(Session session) {
if(!map.containsKey(session)){
map.put(session, new SessionThread(session));
}
}
public static void removeSession(Session session){
if(map.containsKey(session)){
map.remove(session);
}
}
public static void sendData(Session session, byte[] bytes){
if(map.containsKey(session)){
map.get(session).send(bytes);
}
}
public class SessionThread implements Runnable {
private Session session;
private boolean alive = true;
private final LinkedList<byte[]> messageQueue = new LinkedList<>();
public SessionThread(Session session){
}
#Override
public void run() {
while (alive) {
if(Thread.interrupted()){
alive = false;
return;
}
synchronized (messageQueue) {
while(!messageQueue.isEmpty()){
byte[] msg = messageQueue.poll();
try {
session.getBasicRemote().sendBinary(ByteBuffer.wrap(msg));
} catch (IOException ex) {
Logger.getLogger(SessionManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
}
public void send(byte[] bytes) {
synchronized (messageQueue) {
messageQueue.add(bytes);
}
}
public void kill(){
alive = false;
}
}
}

Your SessionThread inner class is not static. That means the compiler generates a constructor to capture the value of this, the enclosing class. Since you're trying to create a new SessionThread in a static method, there is no this to capture. Make the class static.

Edit
#directedition: SessionThread should be a static class. Actually it should be a stand alone interface and class.

Related

Unable to mock creating directory using mkdirs() calls in java void method

While trying to run my test for the following code. I am getting some error detailed below.
I observed at the time it makes mkdirs() calls in my code throws IllegalArgumentException when I try to run my test.
MyClass.java
package com.javaeasily.demos.junit;
import java.util.ArrayList;
public class MyClass {
private final NodeHelper nodeHelper;
private static final ArrayList<String> ACTIVE_SERVICES_POST_RECONFIGURE = new ArrayList<>();
// Only allow construction if number is greater than one
MyClass() {
ACTIVE_SERVICES_POST_RECONFIGURE.add("my-node-" + NodeUtils.getMyNode());
nodeHelper = new NodeHelper();
}
public void reconfigureNode() {
if (ACTIVE_SERVICES_POST_RECONFIGURE.isEmpty()) {
return;
}
try {
nodeHelper.createStagingDir();
} catch (Exception e) {
throw new RuntimeException("Cannot reconfigure node");
}
}
}
NodeUtils.java
package com.javaeasily.demos.junit;
import org.apache.commons.lang3.StringUtils;
public class NodeUtils {
private static final String HOSTNAME_PREFIX = "my-node-";
public static String hostnameToNode(String hostname) {
if (!hostname.startsWith(HOSTNAME_PREFIX)) {
throw new IllegalArgumentException(hostname + " is not recognized hostname");
}
return StringUtils.removeStart(hostname, HOSTNAME_PREFIX);
}
public static String getHostname() {
return System.getenv("HOSTNAME");
}
public static String getMyNode() {
return hostnameToNode(getHostname());
}
}
NodeHelper.java
package com.javaeasily.demos.junit;
import java.io.File;
public class NodeHelper {
private static final String STAGING_DIR = "/staging/";
public void createStagingDir() {
File stagingDir = new File(STAGING_DIR);
if (!stagingDir.exists() && !stagingDir.mkdirs()) {
throw new IllegalArgumentException("Could not create staging dir");
}
}
}
MyClassTest.java
package com.javaeasily.demos.junit;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
#ExtendWith(MockitoExtension.class)
public class MyClassTest {
private MyClass myclass;
#BeforeEach
public void SetUp() {
try (MockedStatic<NodeUtils> nodeUtilsMockedStatic = Mockito.mockStatic(NodeUtils.class);) {
nodeUtilsMockedStatic.when(NodeUtils::getMyNode).thenReturn("foo");
myclass = new MyClass();
}
}
#Test
public void testReconfigureNode() {
myclass.reconfigureNode();
}
}
When I try to run my test I get following error:
java.lang.RuntimeException: Cannot reconfigure node
at com.javaeasily.demos.junit.MyClass.reconfigureNode(MyClass.java:22)
Post debugging I see that:
java.lang.IllegalArgumentException: Could not create staging dir
Does anyone care to enlighten me as to what I am doing wrong?
To mock NodeHelper you should not create it inside MyClass, but inject it from the outside via the constructor. i.e.
MyClass(Nodehelper nodeHelper) {
ACTIVE_SERVICES_POST_RECONFIGURE.add("my-node-" + NodeUtils.getMyNode());
this.nodeHelper = nodeHelper;
}
This allows you to create a mocked NodeHelper in your test, pass it to MyClass and set the desired behavior as expectations.

ConcurrentSkipListMap firstKey() throws NoSuchElementException even though it contains data

I wrote a small application that receives data from a web socket, which I store in static ConcurrentSkipListMap.
The application initially creates a new thread where it runs infinitely while loop calling ConcurrentSkipListMap.firstKey(). After a while, this call throws a NoSuchElementException, even though the ConcurrentSkipListMap contains data.
break point in catch block
Example of my application:
I have cacher class that contains websocket implementation and NavigableMap init:
package solvethat.net.triobot.Example;
import com.binance.api.client.BinanceApiCallback;
import com.binance.api.client.BinanceApiClientFactory;
import com.binance.api.client.domain.event.DepthEvent;
import com.binance.api.client.domain.market.OrderBook;
import com.binance.api.client.domain.market.OrderBookEntry;
import java.math.BigDecimal;
import java.util.Comparator;
import java.util.List;
import java.util.NavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;
public class AskCacher {
private long updateId;
private final BinanceApiClientFactory factory;
public AskCacher() {
factory = BinanceApiClientFactory.newInstance();
initAsks();
runWebsocket();
}
/**
* Init data getting order book snapshot
*/
private void initAsks() {
try {
OrderBook orderBook = factory.newRestClient().getOrderBook("btcusdt".toUpperCase(), 10);
updateId = orderBook.getLastUpdateId();
NavigableMap<Double, Double> asks = new ConcurrentSkipListMap<>(Comparator.naturalOrder());
for (OrderBookEntry ask : orderBook.getAsks()) {
asks.put(Double.parseDouble(ask.getPrice()), Double.parseDouble(ask.getQty()));
}
StaticData.ask = asks;
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
private void runWebsocket() {
factory.newWebSocketClient().onDepthEvent("btcusdt", new BinanceApiCallback<>() {
/**
* Set ask price and call analysis method
*/
#Override
public void onResponse(DepthEvent depthEvent) {
if (depthEvent.getFinalUpdateId() > updateId) {
updateId = depthEvent.getFinalUpdateId();
updateOrderBook(depthEvent.getAsks());
}
}
/**
* Just print err message
*/
#Override
public void onFailure(final Throwable cause) {
System.err.println(cause.getMessage());
}
});
}
/**
* Updates an order book (asks) with a delta received from the server.
* Whenever the qty specified is ZERO, it means the price should was removed from the order book.
*/
private void updateOrderBook(List<OrderBookEntry> orderBookDeltas) {
for (OrderBookEntry orderBookDelta : orderBookDeltas) {
Double price = Double.parseDouble(orderBookDelta.getPrice());
BigDecimal qty = new BigDecimal(orderBookDelta.getQty());
if (qty.compareTo(BigDecimal.ZERO) == 0) {
// qty=0 means remove this level
StaticData.ask.remove(price);
} else {
StaticData.ask.put(price, Double.parseDouble(orderBookDelta.getQty()));
}
}
// Print best ask to see if cacher is alive
System.out.println("btc-usdt best ask: " + StaticData.ask.firstKey());
// Edit map length
if (StaticData.ask.size() > 10) {
StaticData.ask.tailMap((Double) StaticData.ask.keySet().toArray()[10], true).clear();
}
}}
Then infinite loop:
package solvethat.net.triobot.Example;
public class InfiniteLoop {
public void loopProcess() {
Analyzer analyzer = new Analyzer();
while (true) {
analyzer.analyze(StaticData.ask.firstEntry());
}
}}
And analyzer class:
package solvethat.net.triobot.Example;
import java.util.Map;
public class Analyzer {
public void analyze(Map.Entry<Double, Double> entry) {
StaticData.AnalyzeObject analyzeObject = new StaticData.AnalyzeObject();
analyzeObject.setBestAsk(entry.getKey());
if (analyzeObject.getBestAsk() > 50000) {
System.out.println("It is a good price!!");
}
}
}
Static data model:
package solvethat.net.triobot.Example;
import java.util.NavigableMap;
public class StaticData {
public static NavigableMap<Double, Double> ask;
public static class AnalyzeObject {
double bestAsk;
public double getBestAsk() {
return bestAsk;
}
public void setBestAsk(double bestAsk) {
this.bestAsk = bestAsk;
}
}
}
Main class for example run:
package solvethat.net.triobot.Example;
public class Main {
public static void main(String[] arguments) {
new AskCacher();
new Thread(new InfiniteLoop()::loopProcess).start();
}
}
The example only shows how the application is composed, but I was not able to use it to raise an error but I opened my repo as public:
https://github.com/Sick-E/TrioBot
Can anyone please help me?
Thank you.
Tomas
You can replace your code with something like that (no exception handling is required)
Optional.ofNullable(trio.getThirdPair().getBids().firstEntry())
.map(Map.Entry::getKey)
.ifPresent(trio.getTrioAnalysis()::setBidThird);

Designing resource access: Final enums vs static members of extendable classes

I am trying to design a framework for loading resources. So I have two options
Approach 1
Underlying structure: An interface with a simple abstract class implementation and more specific extends.
Access: static final members of class initialized to the class.
Approach 2
Underlying structure: A specific enum from the get go, implementing all interface methods: no leveraging partial implementations of abstract classes.
Access: as enum entries
While approach 1 is a lot more flexible and reusable, I like the way enums provide a clean usable list, ready to use as opposed to static finals with scope for Class.instance.instance.instance. ...
Is there a standard way to do this? Is there a better way to do this?
Though not strictly needed here's the code
Approach 1
Interface LoadableResource<T>
import java.util.ArrayDeque;
import java.util.Queue;
public interface LoadableResource<T> {
Queue<Exception> exceptionQueue=new ArrayDeque<>();
boolean load();//Load the resource and return status
boolean isLoaded() ;
T getResource();
void onLoadFail();
void onLoadSuccess();
void onException(Exception ex);
Queue<Exception> getExcpetions();
}
Abstract SimpleLoadableResource<T>
import java.util.Queue;
public abstract class SimpleLoadableResource<T> implements LoadableResource<T> {
private boolean FLAG_LOADED = false;
private T resource;
#Override
public boolean isLoaded() {
return FLAG_LOADED;
}
#Override
public T getResource() {
return resource;
}
#Override
public void onLoadFail() {}
#Override
public void onLoadSuccess() {}
#Override
public void onException(Exception ex) {exceptionQueue.add(ex); }
#Override
public Queue<Exception> getExcpetions() { return exceptionQueue; }
protected void setLoaded(boolean FLAG_LOADED) {
this.FLAG_LOADED = FLAG_LOADED;
}
public abstract T loader() throws Exception;
#Override
public boolean load() {
try {
resource=loader();
} catch (Exception e) { onException(e); }
if (isLoaded())
onLoadSuccess();
else
onLoadFail();
return isLoaded();
}
}
Specific SimpleLoadableImage
import javax.imageio.ImageIO;
import java.awt.*;
public class SimpleLoadableImage extends SimpleLoadableResource<Image>{
public static final SimpleLoadableImage LOGO1=new SimpleLoadableImage("1.jpg");
public static final SimpleLoadableImage LOGO2=new SimpleLoadableImage("2.jpg");
private final String path;
public SimpleLoadableImage(String path) {
this.path = path;
super.load();
}
#Override
public Image loader() throws Exception {
var res=ImageIO.read(this.getClass().getClassLoader().getResourceAsStream(path));
setLoaded(true);
return res;
}
}
Approach 2
import javax.imageio.ImageIO;
import java.awt.*;
import java.util.ArrayDeque;
import java.util.Queue;
public enum SimpleLoadableImage_Enum {
LOGO1("1.jpg"),
LOGO("2.jpg");
private final String path;
Queue<Exception> exceptionQueue=new ArrayDeque<>();
private boolean FLAG_LOADED = false;
private Image resource;
private SimpleLoadableImage_Enum(String path){
this.path=path;
try {
resource=ImageIO.read(this.getClass().getClassLoader().getResourceAsStream(path));
FLAG_LOADED=true;
} catch (Exception e) {
exceptionQueue.add(e);
}
}
public boolean isLoaded() { return FLAG_LOADED; }
public Image getResource() { return resource; }
public Queue<Exception> getExcpetions() { return exceptionQueue; }
}

How to make a class method only accesible by another class?

Suposse there are a "Worker" class in which one of its attributes is a queue of "WorkOrder" objects, and a "Boss" class which is the only one that can add or delete new "WorkOrders" of this queue. How could it be possible to make the method that modifies the queue only accessible by "Boss"?
I've thought of two solutions:
(a) Make the method package-private, keep the two classes in the same package and instantiate them in another.
(b) Make an interface with the methods that can be accessed by "Worker", make the constructor of this class private and create instead a static method which return an object with the same type than the interface.
What is your opinion? Can you think of a more elegant solution?
Consider having an interface that exposes the worker methods you want to be public. The boss can hold a reference to the implementation (which has the workorders queue getter) and only present the interface to other classes.
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
class Class {
public static void main(final String... args) {
final Boss boss = new Boss();
final Worker worker = boss.getWorker("sivmish");
worker.getWorkItems();//ERROR: only Boss has access to this.
}
}
interface Worker {
void processWork();
}
interface WorkOrder {
void doWork();
}
class WorkerImpl implements Worker {
private final Queue<WorkOrder> workItems;
WorkerImpl() {
this.workItems = new ArrayDeque<>();
}
public Queue<WorkOrder> getWorkItems() {
return workItems;
}
#Override
public void processWork() {
while (!workItems.isEmpty()) {
workItems.poll().doWork();
}
}
}
class Boss {
private final Map<String, WorkerImpl> workersByName;
Boss() {
workersByName = new HashMap<String, WorkerImpl>();
}
public Worker getWorker(final String name, WorkOrder... workOrders) {
if (!workersByName.containsKey(name)) {
final WorkerImpl worker = new WorkerImpl();
workersByName.put(name, worker);
}
final WorkerImpl worker = workersByName.get(name);
worker.getWorkItems().addAll(Arrays.asList(workOrders));
return worker;
}
}
I would rather suggest to keep the queue inside the Boss class,because you want to make it only accessible by the Boss for adding or removing
class Boss
{
public LinkedList<E> queue = new LinkedList<E>();
private void add(item)
{
//do stuff...
}
private void remove()
{//do stuff...}
public static void viewOnly()
{
//display details
}
}
class Workers
{
public workers()
{
Boss.viewOnly();
}
}
class Main
{
public static void main(String args[])
{
Boss b = new Boss();
b.add(1); //job 1
b.add(5); //job 5
/* and so on..
*/
workers w = new workers();
}
}

Java - Thread doesn't want to start

I have this console application, but for some reason the thread's run() method doesn't want to start. The code seems long for the first time but I tried to organize it as much as I can.
The result output:
eThread starting!!
So it seems that CarManager.startFunctionalities() gets executed, but the line eThread.start() is not executed at all because the line "started" is not printed out.
Here is the sourcecode.
The main class:
package rpicar.android;
public class AndroidEmulator{
public static void main(String args[]) throws InterruptedException {
CarManager cm = new CarManager ("localhost");
}
}
CarManager:
package rpicar.android;
import rpicar.common.Direction;
import rpicar.common.EnvironmentData;
public class CarManager {
private MotorManager mManager;
private final String RPIADDRESS = "localhost";
private Thread mThread; //motor
private EnvironmentManager eManager;
private Thread eThread;
public CarManager(String rpiAddress) {
//initialize MotorManager
mManager = new MotorManager(RPIADDRESS);
//Make a thread for the Motor commands
mThread = new Thread(mManager);
//Initialize EnvironmentManager
eManager = new EnvironmentManager(RPIADDRESS);
//Makea thread for collecting EnvironmentData
eThread = new Thread (eThread);
startFunctionalities();
}
public void move(Direction d){
this.mManager.setDirection(d);
}
public EnvironmentData getCurrentEnvironmentData(){
return this.eManager.getCurrentEnvironmentData();
}
private void startFunctionalities(){
//Start MotorManager for sending movement commands when needed.
//mThread.start();
//Start EnvironmentManager to collect EnvironmentData
System.out.println("eThread starting!! ");
eThread.start();
}
}
EnvironmentManager:
package rpicar.android;
import rpicar.common.CarComponent;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import rpicar.common.EnvironmentData;
public class EnvironmentManager extends CarComponent implements Runnable{
private EnvironmentData currentEnvironmentData;
public EnvironmentManager(String rpiAddress) {
super(rpiAddress, 2176, true);
this.currentEnvironmentData = new EnvironmentData();
}
public synchronized EnvironmentData getCurrentEnvironmentData() {
return currentEnvironmentData;
}
public synchronized void setCurrentEnvironmentData(EnvironmentData currentEnvironmentData) {
this.currentEnvironmentData = currentEnvironmentData;
}
#Override
public void run() {
System.out.println("eThread started!! ");
super.connect();
while(true){
try {
this.setCurrentEnvironmentData((EnvironmentData) super.in.readObject());
} catch (IOException ex) {
super.connect();
} catch (ClassNotFoundException ex) {
Logger.getLogger(EnvironmentManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
When you create your instance of eThread, you accidentally pass the thread itself to the constructor (or according to the order of the operations, you pass null).
You should pass eManager to the constructor instead.
eThread = new Thread (eThread);
Would become
eThread = new Thread (eManager);
You can protect yourself in the future from this mistake by making the eThread a final field, so you cannot use it before you declare it.

Categories

Resources