In a project that I'm working on, I would like to have a custom annotation that warns users that this specific method should be called from another thread. I've called it #ThreadNeeded, and I want to achieve the effect of having the compiler warn the user if the method called would be on the main thread. How can I achieve this? I have looked into many guides on Annotations, but none of them actually give a way to make use of them other than just marking the ElementType with the annotation. Here is the source of the annotation I have so far
/**
* An annotation that signifies that this method needs to be run inside a background thread.
*/
#Retention(RetentionPolicy.SOURCE)
#Target(ElementType.METHOD)
public #interface ThreadNeeded {
}
And here is an example usage
#Nullable
#ThreadNeeded
public SonyCamera build(){
try {
send();
} catch (Exception ex){
Log.e(TAG, ex.getMessage(), ex);
return null;
}
return camera;
}
private void send() throws Exception {
final byte[] ssdpreqb = SSDP_REQUEST.getBytes();
DatagramSocket socket;
DatagramPacket recieve, packet;
socket = new DatagramSocket();
InetSocketAddress isad = new InetSocketAddress(SSDP_ADDRESS, SSDP_PORT);
packet = new DatagramPacket(ssdpreqb, ssdpreqb.length, isad);
socket.send(packet);
Thread.sleep(100);
socket.send(packet);
Thread.sleep(100);
socket.send(packet);
boolean searching = true;
byte[] array = new byte[1024];
while(searching) {
recieve = new DatagramPacket(array, array.length);
socket.setSoTimeout(SSDP_TIMEOUT);
socket.receive(recieve);
String replyMessage = new String(recieve.getData(), 0, recieve.getLength(), "UTF-8");
String ddusn = SSDPClient.findParamaterValue(replyMessage, "USN");
String location = SSDPClient.findParamaterValue(replyMessage, "LOCATION");
camera.location = location;
camera.usn = ddusn;
fetch(location);
}
}
In order to process annotations while compiling sources you should write annotation processor and instruct javacto use them.
Here is some kind of tutorial: https://www.javacodegeeks.com/2015/09/java-annotation-processors.html
Though I'm not sure you can detect mentioned threading issues at compile-time.
The GUI Effect Checker may do what you need. The below is taken from its documentation:
One of the most prevalent GUI-related bugs is invalid UI update or invalid thread access: accessing the UI directly from a background thread.
The GUI Effect Checker solves this problem.
The GUI Effect Checker ensures that only the UI thread accesses UI objects. This prevents GUI errors such as invalid UI update and invalid thread access.
The programmer annotates each method to indicate whether:
It accesses no UI elements (and may run on any thread); such a method is said to have the “safe effect”.
It may access UI elements (and must run on the UI thread); such a method is said to have the “UI effect”.
At compile time, the GUI Effect Checker issues errors in the following cases:
A #UIEffect method is invoked by a #SafeEffect method.
Method declarations violate subtyping restrictions: a supertype declares a #SafeEffect method, and a subtype annotates an overriding version as #UIEffect.
Related
Debugging my application, there is an object (only one) of this class:
public class MqttInterface implements MqttPlatformInterfaceObserver{
private MqttMessage lastMessage;
....
public MqttMessage getLastMessage() {
return lastMessage;
}
#Override
public void mqttMessageArrived(String message) {
try {
lastMessage = new JSONParser().parseJsonBodyAs(MqttMessage.class, message);
}
catch (IOException e) {
e.printStackTrace();
}
}
}
The void mqttMessageArrived(String) method is implemented using an Observer design pattern, so the object is registered and notified when a new message arrives.
I have two breakpoints (one in each method body) At some point after some time application is running, I get that when getLasMessage() message is passed to the object, it is returning a old lastMessage object with old state. Although mqttMessageArrived(String) is being called later several times the lastMessage object returned by getLastMessage() method keep being the same and it is never updated .
I check that the lastMessage attribute is being updated by mqttMessageArrived method (no Exception is thrown) and indeed when the program stops in the mqttMessageArrived method because the breakpoint, I see lastMessage state is being updated, but after that when the program stops in getLastMessage method(), it has the same old state.
I dont understand how this behaviour is possible for the same object, I have been thinking it is related with some concurrency or some cache issue.
I have a server with multiple clients. It uses one server socket and two thread pools for receiving and handling requests from remote clients: one pool - for handling clients connections, and another one - for processing clients remote tasks. Each client sends asynchronous tasks with unique task ID (within each connection) and a bunch of parameters. Upon task deserialization, the server looks up the corresponding service, invokes the given method on it, wraps the result along with the task ID into the answer object and sends it back to the client using ObjectOutputStream.
Since tasks are handled concurrently, two or more threads might finish processing tasks for one client at the same time and try to compete for the ObjectOutputStream.
What happens next? I mean, do they write their objects to output stream atomically or should I synchronize their access to ObjectOutputStream, so that to avoid situation when one thread writes half of its object - then another thread intervenes and... as a result, a sort of Frankenstein object will be send to the client.
import java.io.*;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;
import java.util.concurrent.*;
public class Server {
private final ExecutorService connExecutor = Executors.newCachedThreadPool();
private final ExecutorService tasksExecutor = Executors.newCachedThreadPool();
public void start() {
try (ServerSocket socket = new ServerSocket(2323);) {
while (true) {
try (Socket conn = socket.accept()) {
connExecutor.execute(() -> {
try (ObjectInputStream in = new ObjectInputStream(conn.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(conn.getOutputStream())) {
while (true) {
RemoteTask task = (RemoteTask) in.readObject();
tasksExecutor.execute(() -> {
handleTask(task, out);
});
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
});
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void handleTask(RemoteTask task, ObjectOutputStream out) {
RemoteAnswer answer = new RemoteAnswer();
// unwrap remote task
// lookup local service
// invoke task's method
// wrap result into remote answer
// send answer to the client
try {
out.writeObject(answer);
} catch (IOException e) {
e.printStackTrace();
}
}
}
This here says it nicely:
Is writing an object to an ObjectOutputStream a thread-safe operation?
Absolutely not.
So, yes, your code needs to take precautions itself.
As a rule of thumb: If the documentation doesn't specify that a certain class is thread-safe, it probably isn't. Thread-safety clearly is an "intentional quality" (allusion to Roman Elizarov's blog post, one of Kotlin's language designers) and should therefore always be mentioned.
However, if you're still unsure whether a class of the Java SE-library provides thread-safety or not (as it might be mentioned somewhere else, e.g. the superclass' documentation), you might also just take a quick glance at the type's source code. As you can see, ObjectOutputStream doesn't implement any synchronization mechanisms.
Please see the updates below.
I have a Spring Boot application where I accept TCP/IP connections:
public MyClass implements InitializingBean {
#Override
public void afterPropertiesSet() throws Exception {
try (ServerSocket serverSocket = new ServerSocket(port)) {
while (true) {
Socket socket = serverSocket.accept();
new ServerThread(socket).start();
}
}
}
...
private class ServerThread extends Thread {
#Override
public void run() {
try (InputStream input = socket.getInputStream();
OutputStream output = socket.getOutputStream()) {
// Read line from input and call a method from service:
service.myMethod(lineConvertedToMyObject);
} catch {
...
}
}
}
}
Now this works fine, as it is. But when I introduce AspectJ to myMethod:
#Aspect
#Component
public class MyServiceAspect {
private static final Logger logger = LoggerFactory.getLogger(MyServiceAspect.class);
#Around(value = "execution(* com.package.to.MyService.myMethod(..))")
public MyObject rules(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
MyObject obj = (MyObject) joinPoint.proceed();
logger.debug("Took {} milliseconds", System.currentTimeMillis() - startTime);
return obj;
}
}
service.myMethod is not called and the thread is blocked. What am I missing?
Update:
So here's the deal: MyService, MyServiceImpl and MyServiceAspect are all in the same package. Moving MyServiceAspect into another package made it work.
Does this ring a bell for anyone? Happy to award the bounty to anyone explaining this behavior. Thanks!
Update 2:
Yet another solution: Adding #DependsOn(value = {"myServiceAspect"}) on top of MyServiceImpl again resolves the issue, still wondering why though.
Actual problem
As it was described by Alexander Paderin >> in his answer to the related question >> infinite loop in the afterPropertiesSet() was the thread blocker, since control wasn't return back to Spring in this case.
1. Working example with your samples (not actual after question edit)
Code samples you've provided do not contain issues directly, AspectJ declaration is fine.
First of all, please let me share working example: spring-aspectj-sockets. It is based on Spring 5.1.0 and AspectJ 1.9.1 (currently latest versions) and uses your samples, works independent of the location/package of MyServiceAspect.
2. Issue explanation
2.1. Intro
The most possible thread blocker in your samples is a call to ServerSocket.accept(), javadocs for this method says:
Listens for a connection to be made to this socket and accepts it. The method blocks until a connection is made.
There are 2 correct ways of handling accept():
To initialize connection first, e.g.:
serverSocket = new ServerSocket(18080);
clientSocket = new Socket("127.0.0.1", 18080); // initializing connection
Socket socket = serverSocket.accept(); // then calling accept()
Set up timeout to wait for acceptance:
serverSocket = new ServerSocket(18080);
serverSocket.setSoTimeout(5000); // 5 seconds timeout
Socket socket = serverSocket.accept(); // then calling accept()
NOTE: If within 5 seconds there will be no connections, accept() will throw exception, but will not block the thread
2.2. Assumption
I assume that you are using 1-st approach and somewhere you have a line which initializes the connection, i.e. clientSocket = new Socket("127.0.0.1", 18080);.
But it is called (e.g. if static declarations are used):
After serverSocket.accept() in case MyServiceAspect is located in the same package and
Before - in case MyServiceAspect is located in some other place
3. Debugging
I'm not sure if this is needed, have doubts because of bounty's description, let me cover this quickly just in case.
You can debug your application using Remote Debugging - it will cover aspects, child threads, services, etc. - you will only need to:
Run Java with specific arguments like it is described in this question >>
And connect to the specified debug port using IDE (steps for Eclipse are described in the same question)
I would like to start off by saying that if you know a better way to do this, please tell me. I would rather know a better way of doing this than doing it incorrectly.
I am writing a server program that has to interact with multiple clients. I am using the method that this answer proposed. (socket programming multiple client to one server). I am creating the new Instance of the 'EchoThread'.
I also have another class that has a number of variables that need to be able to be accessed and changed by ALL the classes / operations in my server. I am wondering how I inject (I think that is what it's called) the Instance of that from the class creating the new 'EchoThread' object and the 'EchoThread' Class.
Part of the answer from the link above:
while (true) {
try {
socket = serverSocket.accept();
} catch (IOException e) {
System.out.println("I/O error: " + e);
}
// new threa for a client
new EchoThread(socket).start();
}
I have the Instance of the class I want to inject:
VarsClass vars = new VarsClass();
I normally "link" these by doing thing:
VarsClass vars = new VarsClass();
ExampleClass example = new ExampleClass();
example.link(vars);
Here is the 'link' method in the 'ExampleClass'
public void setGlobalVariables(GlobalVariables global) {
this.globalVariables = global;
}
How do I reference the 'EchoThread' like I do in the above example with 'ExmapleClass' and 'VarsClass'? I am doing this, so each class is not creating a new instance of the VarsClass. (Avoiding the problem I had here: Using the same variables in two threads, but I don't know why they won't update in Java)
Thank you to every one in advance for your patience and help.
~Rane
How do I reference the EchoThread ...
The simple way is like this:
EchoThread et = new EchoThread(socket);
et.link(vars);
et.start();
Or pass the vars object as another argument to the constructor.
Note that the following variant is wrong ... unless you make EchoThread thread-safe.
EchoThread et = new EchoThread(socket);
et.start();
...
et.link(vars);
(It is safe to pass the argument prior to the start() call because there is an explicit "happens before" on the start() call ... between the thread that calls start() and the starting of new thread's run() method.)
The other thing to note is that writing subclasses of Thread is generally considered to be a poor way of implementing multi-threading. A better way is to implement your thread's logic as a Runnable; e.g.
public class MyRunnable implements Runnable {
// thread state variables here ...
public MyRunnable(Socket sock, GlobalVariables vars) {
...
}
public void run() {
// thread logic goes here ...
}
}
and the use it like this:
new Thread(new MyRunnable(sock, vars)).start();
This approach allows you to easily change your code to use a thread pool or an Executor instead of a Thread that you create on the fly. (Creating threads on the fly tends to be expensive.)
You can do it the same way as with instances of any other class.
EchoThread thread = new EchoThread(socket);
thread.setGlobalVariables(globalVars);
thread.start();
I am using OpenCYC api (no too common, besides the point though), and I am trying to create an object AccessObject named ao. The problem is, for whatever reason, an AccessObject cannot be instantiated inside the main Java Swing Event Thread.
So as a workaround, I made another thread that just instantiates an AccessObject in it's run() method and also provides a getter for it to return it.
So this is what I have for the calling code:
// do something with code
AccessObject ao;
AccessObjectInstantiateThread aoThread = new AccessObjectInstantiationThread();
aoThread.start();
while(ao == null) // while loop to ensure we "wait" for aoThread to finish
{
ao = aoThread.getAoObject();
}
// Then use ao however you want
Now this code works, but it seems pretty rediculous. Is there any better way to do this? Remember, there is no way I can instantiate an AccessObject under the main java event thread.
Thank you very much, Rich.
Instantiate it in a SwingWorker object, and check for a valid object before completing the doInBackground() method.
Add a PropertyChangeWorker to the SwingWorker that listens for SwingWorker.StateValue.DONE, then pass the object to your Swing program.
For example,
class MySwingWorker extends SwingWorker<AccessObject, Void> {
public AccessObject doInBackground() throws Exception {
// do whatever needed to create your AccessObject and check its completion
// return your AccessObject
}
}
In your Swing code:
final MySwingWorker mySwingWorker = new MySwingWorker();
mySwingWorker.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChanged(PropertyChangeEvent pcEvt) {
if (pcEvt.getNewValue() == SwingWorker.StateValue.DONE) {
try {
ao = mySwingWorker.get(); // ao is an AccessObject class field
// you can use ao here
} catch (whaeverExceptionYouAreTrapping e) {
// do something with exception
}
}
}
});
mySwingWorker.execute();
Note, code note tested nor compiled.
Edit as per JB Nizet's recommendation you could also simply do an anonymous inner class in your Swing code and skip the PropertyChangeListener:
new SwingWorker<AccessObject, Void>() {
public AccessObject doInBackground() throws Exception {
// do whatever needed to create your AccessObject and check its completion
// return your AccessObject
}
public void done() {
try {
ao = mySwingWorker.get(); // ao is an AccessObject class field
// you can use ao here
} catch (whaeverExceptionYouAreTrapping e) {
// do something with exception
}
}
}.execute();
Your code may not work. You should at least declare your variable as follows:
volatile AccessObject ao;
The reason is, your EDT thread may cache the value of ao variable as an optimization and may not see ao is assigned to a new value.
I hope this code is at the beginning of you application and users will not see UI is not responding.
Ideally you would create AccessObject ao on the start up thread (in the main() method) and not start your UI (EventQueue.InvokeLater with a runnable containing something like new JFrame) until after you had.
Failing that, make ao volatile. Your instantiation code should set this value directly rather than bothering about a "get" method. It should probably also call InvokeLater with a runnable to readjust the display--maybe enable a button or two and send the user a message that things are now possible that were not possible before.
Any code accessing ao has to be prepared for the fact that it may be null; your GUI has to work both ways, making its situation clear to the user. Every check or reference should look something like:
final AccessObject local_ao = ao;
if (local_ao != null) {
// Do things. USE local_ao, NOT oa!!!
}
In short, always use local_ao, which won't change. Remember that the value of ao can and will change at any time. As you've described it, it will only change from null to non-null, and do so only once, but that may change as your code evolves. (If it won't evolve, my first suggestion might be best.)
Your UI (EventQueue) code should not wait for anything. Threads are pain, and I'd take a little delay in the UI over using a thread any day. But you've already paid the price for a thread, so you may as well get your money's worth.