#Around #Aspect in the same package only works with #DependsOn - java

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)

Related

Should I synchronize ObjectOutputStream.writeObject(Object)?

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.

Concurency at a thread pool in Java

I face this problem in Java.
I have a server class named MyServer and I want to implement a thread pool where each thread runs a method of MyServer when a request comes. I have created another class that implements a server pool named MultiThreadedSocketServer. The class is this:
public class MultiThreadedSocketServer {
public void startServer(MyServer s, int localport, int threadPoolSize) {
final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(threadPoolSize);
Runnable serverTask = new Runnable() {
#Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(localport);
System.out.println("Waiting for clients to connect...");
while (true) {
Socket clientSocket = serverSocket.accept();
clientProcessingPool.submit(new ClientTask(clientSocket, s));
}
} catch (IOException e) {
System.err.println("Unable to process client request");
e.printStackTrace();
}
}
};
Thread serverThread = new Thread(serverTask);
serverThread.start();
}
}
the class named MultiThreadedSocketServer has an argument named Server s which passes it in client Task class which a thread is created. The client task class is this:
class ClientTask implements Runnable {
private final Socket clientSocket;
private MyServer s;
public ClientTask(Socket clientSocket, MyServer s) {
this.s = s;
this.clientSocket = clientSocket;
}
#Override
public void run() {
System.out.println("Got a client !");
String inputLine = null;
try {
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
// Do whatever required to process the client's request
inputLine = in.readLine();
if (inputLine.equals("Bye")) {
System.out.println("Bye");
System.exit(0);
}
s.handleRequest(inputLine);
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
As you can see when a request comes the handleRequest method of class MyServer is invoked. I want to make this method to run synchronized, meaning only one thread at a time to be able to run this method. Adding synchronized before the method implementation does not achieve anything.
Can anybody give me the proper way to do this?
Thanks in advance for your time.
PS: I added the whole code
MyServer Class
http://pastebin.com/6i2bn5jj
Multithreaded server Class
http://pastebin.com/hzfLJbCS
As it is evident in main I create three requests with handleRequest with arguments Task, task2 and Bye.
The correct output would be
Waiting for clients to connect...
Got a client !
This is an input Task
Request for Task
Got a client !
This is an input task2
Request for task2
Got a client !
This is an input
Bye
But Instead the order is mixed. Sometimes Bye which shuts the server can be executed first. I want to ensure that the order is the one where the requests are created in the main.
But Instead the order is mixed. Sometimes Bye which shuts the server can be executed first. I want to ensure that the order is the one where the requests are created in the main.
You say that you want the server to handle requests in order. This is hard to ensure because you are opening up 3 sockets and writing them to the server but not waiting for any response. This is implementation dependent but I'm not sure there is any guarantee that when the client returns from doing a socket InputStream write, that the server has received the bytes. This means that from the client side, there is no guarantee that the IO completes in the order that you want.
To see if this is the problem, I would remove the System.exit(0) to see if the other lines make it, just after the "Bye" string does. Or you could put a Thread.sleep(5000); before the exit(0).
A simple sort-of fix would be to make sure your PrintStream has auto-flush turned on. That at least will call flush on the socket but even then there are race conditions between the client and the server. If the auto-flush doesn't work then I'd have your client wait for a response from the server. So then the first client would write the first command and wait for the acknowledgement before going to the 2nd command.
In terms of your original question, locking on the server wouldn't help because of the race conditions. The "Bye" might make it first and lock the server fine.
These sorts of questions around how to synchronize the threads in a multi-threaded program really make no sense to me. The whole point of threads is that they run asynchronously in parallel and don't have to operate in any particular order. The more that you force your program to spit out the output in a particular order, the more you are arguing for writing this without any threads.
Hope this helps.
If the problem is that the bye message kills the server before other requests can be handled, one solution could be to not call System.exit(0); on bye.
The bye message could set a flag block further requests from being handled and also notify some other mechanism to call System.exit(0); when the thread pool is idle with no requests left to handle.

How To Make Java Annotations Useful

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.

Sockets with OSGi: Bundle stopped, socket still open

I'm facing this issue working with a ServerSocket inside one of my bundles, let's just call it: FooBundle.
This FooBundle has, among others, a SocketListener.java class. This class is a Thread and to make a little overview of it, I'll paste some pseudocode:
public class SocketListener implements Runnable{
ServerSocket providerSocket;
Socket connection = null;
private boolean closeIt = false;
public void run() {
try {
//Create the server socket
providerSocket = new ServerSocket(41000, 10);
} catch (IOException e1) {
//catching the exception....
}
while(!closeIt){
try{
connection = providerSocket.accept();
in = new Scanner(new InputStreamReader(onnection.getInputStream()));
while(in.hasNext() !=false)
message = message + " "+in.next();
// bla bla bla...
} catch (IOException e) {
//bla bla...
}
finally{
try{
if (message.equalsIgnoreCase("bye"))
providerSocket.close();
closeIt = true;
}
catch(IOException ioException){
//........
}
}
As you can see, it's a simple thread that waits for a connection until the message it receives from one of the SocketClients is "bye".
This is the problem I'm facing right now: When the Bundle is stopped, I do need to restart the entire OSGi framework : If I try to restart the bundle, a java.net.BindException message is thrown: "Address already in use". So, I stopped the bundle but the socket hasn't been closed.
In OSGi, you need to take care of what the stop() method inside the Activator must include, but I just can't pass any reference of an anonymous thread to the Activator.
Imagine that this is my class diagram inside the bundle:
**FooBundle**
|__FooBundleActivator
|__FooImpl
|__SocketListener (thread)
The SocketListener thread is called from the FooImpl class as an anonymous thread.
My question is: Is there any appropiate method to have such control of anonymous threads and specifically in my case, of non-closing socket ports, inside the OSGi paradigm?
Thanks in advance.
If your bundle is told to stop then assume the guy doing the stopping knows what he is doing. Yes, your protocol expects the 'bye' but shit happens, any protocol that has problems with these things is too fragile for the real world. In general, all your tasks in OSGi should have a life cycle. So this would be my code (using DS instead of activators).
#Component
public class ProtocolServer extends Thread {
volatile ServerSocket server;
volatile Socket connection;
public ProtocolServer() {
super("Protocol Server on 4100"); // to identify the thread
}
#Activate void activate() {
setDaemon(true);
start();
}
#Deactivate void deactivate() {
interrupt();
// best effort close (even if null)
try { server.close(); } catch(Exception e) {}
try { connection.close(); } catch(Exception e) {}
join(10000); // waits 10 secs until thread exits
}
public void run() {
// loop for active component
while( !isInterrupted() )
try {
doServer();
} catch( Exception e) {
log(e);
// bad error, accept failed or bind failed
// or server socket was closed. If we should remain
// active, sleep to prevent overloading the
// system by trying too often, so sleep
if ( !isInterrupted() )
try { Thread.sleep(5000); } catch(Exception e) {}
}
}
private void doServer() throws Exception {
server = new ServerSocket(4100)
try {
while( !isInterrupted() )
doConnection(server);
} finally {
server.close();
}
}
private void doConnection(ServerSocket server) throws Exception {
connection = server.accept();
try {
doMessages(connection);
// the pseudo code exits here, but that seems
// kind of weird? If desired, interrupt
// this object, this will exit the thread
} catch( Exception e) {
log(e); // the connection failed, is not uncommon
} finally {
connection.close();
connection = null;
}
}
private void doMessages(Socket connection) {
MyScanner s = new MyScanner(socket);
String msg;
while( !isInterrupted() && !"bye".equals( msg=s.getMessage()))
process(msg);
}
}
One important design consideration in OSGi is that the components keep working even if there are failures. In a network you often have transient errors that go away on their own. Even if they don't it is desirable that the server keeps on trying while you fix the problem. Your pseudo code would be a nightmare in practice since it would disappear on any error. Any system with multiple such components tends to becomes quickly unstable.
One thing that also surprised me is that you only support one connection at a time. In general it is better to not limit this and handle the messages in their own thread. In that case, you must ensure that each created handler for a connection is also closed appropriately.
Instantiate the ServerSocket outside (probably in the Activator) and pass it to the SocketListener via a constructor. You can call serverSocket.stop() in the stop function of the Activator than.
In case you call ServerSocket.stop() a SocketException will be thrown that is a subclass of IOException. Please think of handling IOException in the while iteration in the way that it will stop executing the iteration for sure.
You need to close that listening socket regardless of the message before exiting the thread function. Then what should really make a difference for you is calling setReuseAddress(true) on that socket to allow binding the port while old connection hangs in the timeout state.
And, please please please, use better indentation technique in your code ...

Multithreaded Java server: allowing one thread to access another one

Hopefully the code itself explains the issue here:
class Server {
public void main() {
// ...
ServerSocket serverSocket = new ServerSocket(PORT);
while (true) {
Socket socket = serverSocket.accept();
Thread thread = new Thread(new Session(socket));
thread.start();
}
// ..
}
public static synchronized Session findByUser(String user) {
for (int i = 0; i < sessions.size(); i++) {
Session session = sessions.get(i);
if (session.getUserID().equals(user)) {
return session;
}
}
return null;
}
}
class Session {
public Session(Socket socket) {
attach(socket);
}
public void attach(Socket socket) {
// get socket's input and output streams
// start another thread to handle messaging (if not already started)
}
public void run() {
// ...
// user logs in and if he's got another session opened, attach to it
Session session = Server.findByUser(userId);
if (session != null) {
// close input and output streams
// ...
session.attach(socket);
return;
}
// ..
}
}
My question here is: Is it safe to publish session reference in Server.findByUser method, doesn't it violate OOP style, etc?
Or should I reference sessions through some immutable id and encapsulate the whole thing? Anything else you would change here?
String sessionId = Server.findByUser(userId);
if (sessionId != null && sessionId.length() > 0) {
// close input and output streams
// ...
Server.attach(sessionId, socket);
return;
}
Thomas:
Thanks for your answer.
I agree, in a real world, it would be a good idea to use dependency injection when creating a new instance of Session, but then probably also with an interface, right (code below)? Even though I probably should have unit tests for that, let's consider I don't. Then I need exactly one instance of Server. Would it then be a huge OO crime to use static methods instead of a singletone?
interface Server {
Session findByUser(String user);
}
class ServerImpl implements Server {
public Session findByUser(String user) { }
}
class Session {
public Session(Server server, Socket socket) { }
}
Good point on the attach(...) method - I've never even considered subclassing Session class, that's probably why I haven't thought how risy it might be to call public method in the constructor. But then I actually need some public method to attach session to a different socket, so maybe a pair of methods?
class Session {
public Session(Socket socket) {
attach_socket(socket);
}
public void attach(Socket socket) {
attach_socket(socket);
}
private void attach_socket(Socket socket) {
// ...
}
}
It's true that allowing clients of Session to call attach(...) doesn't seem right. That's probably one of those serious mehods only the Server should have access to. How do I do it without C++'s friendship relationship though? Somehow inner classes came to my mind, but I haven't given it much thought, so it maybe a completely wrong path.
Everytime I receive a new connection I spawn a new thread (and create a new Session instance associated with it) to handle transmission. That way while the user sends in a login command, Server is ready to accept new connections. Once the user's identity is verified, I check if by any chance he's not already logged in (has another ongoing session). If he is then I detach the onging session from it's socket, close that socket, attach the ongoing session to current socket and close current session. Hope this is more clear explanation of what actually happens? Maybe the use of a word session is a bit misfortunate here. What I really have is 4 different objects created for each connection (and 3 threads): socket handler, message sender, message receiver and a session (if it's a good solution that's a different question...). I just tried simplyfing the source code to focus on the question.
I totally agree it makes no sense to iterate over session list when you can use a map. But I'm afraid that's probably one of the smaller issues (believe me) the code I'm working on suffers from. I should've mentioned it's actually some legacy system that, no surprise, quite recently has been discoved to have some concurrency and performance issues. My task is to fix it... Not an easy task when you pretty much got only theoretical knowledge on multithreading or when you merely used it to display a progress bar.
If after this, rather lengthy, clarification you have some more insight on the architecture, I'd be more than willing to listen.
You should start by making the Server class OO (i.e. not static) and use dependency injection in the Session class:
class Server {
public Session findByUser(String user) { }
}
class Session{
public Session(Server server, Socket socket){}
}
public void attach(..) has to be private to ensure encapsulation and proper initialization. A subclass could break the Session class otherwise like this:
class BadSession extends Session{
#Override public void attach(Socket socket) {
//this is not initialized at this point
//now the instance is broken
}
}
Calling attach from a client seems to be invalid, too.
The responsibility to attach the Socket to the Session should be part of the Server. This is the right place to decide which Session gets which Socket. As far as I do understand your code you are creating a Session with a Socket. Somehow you find out that the user already has a Session (with another Socket). Now you attach the current Session to this Socket. There is now the old Socket with two Sessions and the new Socket without a Session. I think the a traditional Session should have multiple Sockets not the other wayaround:
Session session = findSession(userId);
session.attach(socket);
class Session{
List<Socket> sockets;
}
After this change the threads would not be assigned to Sessions but socket handlers, that process the input stream for one socket and change the Session accordingly.
Using synchronized for the method public static synchronized Session findByUser(String user) is not sufficient to ensure thread-safeness. You have to make sure that the look up of a session (by user) and the registration a session (if the user is not known) have to be atomic. The semantic should be analogous to putIfAbsent of ConcurrentMap. (Iterating over the session List is not efficient anyway. You should use a Map<Id, Session>.)
I hope this helps.

Categories

Resources