JAVA: How to set thread name (RMI)? - java

After my research and discussion here I decided I need to set the same name for threads on different JVMs which belong to the same control flow in the distributed system. Threads are created e.g. by RMI. Is it possible to set name when thread is created in that way?

There's no automatic means to transfer this info from client-to-server.
It sounds like you want/need some sort of Context object set up on the client (per-thread?) and passed as a method argument to your RMI servers. That Context object could contain not just the thread-name, but perhaps also other info like the calling process pid etc.
You'd then have to use that Context object to set thread-names etc. accordingly via Thread.setName() once it's been passed across the wire. Going forwards, you could set up context-specific info in your logging framework using this (e.g. using Log4j nested diagnostic contexts)
The use of aspects to automate this further is left as a further exercise for the reader :-)

The Thread class has a static method to setName(String). If you can have your threads, wherever they come from, running that method, you should be good to go. These guys had similar issues with Tomcat related threads.

Related

Change a node's Instance Name when connecting to Axon Server

I'm currently putting together integration tests for a Spring Boot / Axon application.
In one of these tests, it (a node) creates another node via SpringApplicationBuilder (under a different profile), connecting to the same Axon Server instance as its creator.
The problem I'm having is that event handling starts to behave weirdly, I believe that any 'common' event handlers on the original application with the second created node get ignored/lost.
Everything seems to behave normally when the instances are started outside of the test environment.
My thought is that in the test, the two nodes end up sharing an Instance Name on Axon Server (as they share a processId and hostname), which messes with handler registration/tracking. Does this make sense?
Is there a way that I can manually set this value for nodes connecting to Axon Server so that this doesn't occur during testing?
I am not sure which components are started by the outer test application, and which are started by the inner one. Beware that there are multiple aspects that could get in your way here.
AxonServer may be confused and believe the two components are actually the same. Indeed, the hostname and processId for both will be the same, which causes AxonServer to believe it is just dealing with multiple connections from the same application. To circumvent that, you can define a different clientId, using the axon.axonserver.clientId property. Just set that to a random value, and that should take care of that part of the problem.
Another issue is that your components may have tracking processors with the same name. In that case, AxonServer will see both instances of the processor as multiple instances of the same processor, and balance the load between the two (if enough segments are present). If you only have one processing segment available, then only one handler will be active. The other component will not receive any events.
To circumvent this, prefix the names of your processors with something unique, in your test cases. You can use the EventProcessingConfigurer's assignProcessingGroup(Function<String, String> assignmentRule) method to change the rule of assigning groups to processors. By default, the name of the processor is identical to the name of the group. In your case, you could (based on the test profile you set), add a unique test-related prefix to the processor name. That will 'trick' Axon into believing they are different processors, and need to run concurrently.
I'd recommend trying option 1 first. If that doesn't suffice for the test, you could try the second one as well.

Retain Non-Serializable Object's Values After Tomcat Reloaded

My program has to go through a learning step that takes around 15 mins to complete. The result of this learning is two Models stored into two public objects which will be then used in other classes. I put this learning step in the following method:
public void init()
So as to be performed at the start of the server. The problem is, every time the server reloads, it re-does the learning step. I have to wait another 15 minutes just to see the effects of a small change. I was wondering if there is a way to retain the value of some objects throughout the running of the program and the server. Here is my code:
public static Model model1;
public static Model model2;
#Override
public void init()
{
model1= readModel(source1)
model2= readModel(source2)
}
PS. I am using Servlets with JSP pages and Tomcat Server.
Make it a session- or application-scoped bean, as appropriate, and access it as a bean rather than a normal object.
As a general solution, I would suggest for you to keep the learning part and the model out of service container. Possibly a different VM / process. This way you will be able to retain the model for as long as the process is required to run, independent of the state of client process that is your tomcat.
DETAILED
You can achieve this in few steps
First, you need to migrate model preparation and caching to a different program. This program will run as a daemon and you can use Daemon by Apache to run it as a background service
Second, Assuming your daemon is up and running, your model consumer can communicate with the model VM using standard protocols. The selection of protocol depends on your exact requirements. It can be an API exposed over TCP/HTTP or RMI or anything else.
ALTERNATIVELY
As I suggested in comments, you can also dump the model binary to file system once the model is trained. Cache the model on tomcat startup. The io will be much faster than learning phase.
You could have a look here?
The Idea is either save session somewhere and put your model objects there or just use Hazelcast (overkill probably :))

Scope of Static Class Variables in Java

I have a static object defined in my logging class, along the lines of:
class myLoggingClass {
static java.util.Properties properties;
...
...
}
According to my reference book, this means that the properties object is shared by all instances of my class.
I find this definition insufficient. I'm writing a class that is being invoked more than once in each application on our project.
Further, our project uses several web services running in the same tomcat container. Each web service may have multiple threads.
The Java Virtual Machine running on the host may also run one or more web service client applications, which run external to tomcat.
So by this definition, I may have tomcat running multiple web services with threads, each having several objects, which may contain an instance of my class.
There may also be one or two web clients running outside of tomcat, but within the same JVM. Would all of these instances of my class share the same properties object? That would make it JVM-wide.
If the static object is not JVM-wide, does anyone know at what level each one would exist? One per tomcat container? One per web service, and one per standalone web service client application?
The reason: When I update my properties, I'm getting a java.lang.ConcurrentUpdateException from java.util.Properties.
I'm using a static boolean variable to "lock" the properties object when my class updates it, but this is not keeping the exception from occurring.
This leads me to believe that the static object used in my class may not be at the same scoping level as the one used in java.util.Properties... But that's just a guess.
Thanks for any help.
Statics aren't "shared by all instances of a class" - they're unrelated to instances; they belong to the type itself. In particular, static variables are perfectly usable without any instances being created.
That gives a clue as to the scope of statics: they're scoped by the Class object representing the containing class, which is in turn scoped by the ClassLoader that loaded it.
Depending on where the library is placed, the static variable may be JVM-wide or web-application wide - or possibly something in between, if Tomcat supports multiple hosting (I can't remember offhand).
Look at the Tomcat documentation for how the libraries are laid out and how they relate to class loaders. For example, here's the Tomcat 6.0 ClassLoader how-to guide, and the equivalent for 5.5.
How does your Boolean "lock" work? You should really use a proper lock (synchronized) to make sure that every use of the properties object (both read and write, including locking for the whole period during which you iterate through it) is appropriately locked.
Instead of changing the "live" Properties object, have you considered treating that as immutable - so when you want to update the properties, you take a copy, change that, and then make the copy the "live" version? You'd still need to prevent two different threads from making changes at the same time (or you'd lose some) but it's likely to make the reading side a lot easier and more efficient.
You may find that the scope of such a static variable is limited to one per ClassLoader that has loaded your class. I'm not sure how Tomcat arranges its ClassLoaders, so it's hard to say what the extent of the scope will be in that environment.
The likely cause of your ConcurrentModificationException is that you are iterating thru the values/entries of the Properties object in one thread while another modifies it at the same time. You cannot do this.
Can you elaborate on the locking mechanism that you mention here:
I'm using a static boolean variable to "lock" the properties object when my class updates it, but this is not keeping the exception from occurring.
?
Because it doesn't sound as if you are using the built-in locking and synchronization methods in Java.
Something like this should prevent threads from reading the Properties object while another thread updates it:
static Object lockObject = new Object();
...
synchronized(lockObject) {
// access the Properties object
}
Note that you will need to do this every time you access the Properties object, either to read it or modify it.
Also I would never recommend static objects to share data among all instances or static lockObjects - global data is evil - but it sounds as if you need this for some reason.
Could it be a classloader problem where the jar that contains your class is duplicated in each WEB-INF/lib of your different applications?
If so, I would try to add this jar to Tomcat libs and not to the application.

web service client reference, in a servlet

I have a servlet, and that servlet uses a .net web service to perform some function. To do this, I created the webservice client in Netbeans using the "jax-rpc" style client.
Let's say that my service name is "Tester". Then two of the generated classes are called "Tester", and "TesterSoap".
To get a reference to the web service, I need to do this:
Tester t = new Tester_Impl();
TesterSoap tsoap = t.getTesterSoap();
To use the webservice, I can then do this:
tsoap.runTest();
My question is, since this is a servlet which gets executed many times, should I store the first two lines in static variables (so they only ever get executed once), or store them locally so that they execute everytime the servlet is executed?
Another way of asking the same question: is there a performance hit everytime the first two lines are called? (I'm testing everything locally so it's hard to measure).
Thanks...
If the default constructor and any of the initialization blocks of the Tester_Impl() class and the method getTesterSoap() doesn't do anything expensive (e.g. reading file from disk, loading data from DB, connecting a socket, etc, I however suppose it doesn't) then you don't need to worry about it.
You can consider declaring them as an instance variable of the class extending from HttpServlet. But, a big but, it is going to be shared among all HTTP requests, because there will be only one instance of the particular servlet class during whole application's lifetime. So if the Tester_Impl class is supposed to have a state, then it is a very bad idea to declare it as an instance variable. It would then be shared among all requests. With other words, it's not threadsafe. If you want to ensure threadsafety in servlets, then declare everything in the very same method block.
I would not optimize prematurely here. Test this out in as close to a production environment as you can (i. e. not on your local box) and see what the performance hit is. What I've done in the past is write a small shell script that hits my server with wget n times with a delay of k milliseconds and then measured the latency, possibly instrumenting the code with some timing or profiling myself (or with jvisualvm or some other profiling tool).
If you want to protect your design from a possible performance hit without doing the testing, you could use a factory to provide instances of the service client and then you could swap out singleton service clients for many of them whenever you feel like it.

Logging activities in multithreaded applications

I have a layered application in Java which has a multi thread data access layer which is invoked from different points. A single call to this layer is likely to spawn several threads to parallelize requests to the DB.
What I'm looking for is a logging tool that would allow me to define "activities" that are composed by various threads. Therefore, the same method in the data access layer should log different outputs depending on its caller. The ability to group different outputs to summarize the total cost of an operation is also important.
Although the application is in Java, language is not a restriction; what I need are the design guidelines so to eventually implement it. We are currently using log4j, but can't get this behaviour from it.
You should also have a look at the nested diagnostic context feature of log4j. Pushing different contexts to the logger for different callers might do the trick for you.
You should be able to pass a logger around, so you create a logger based on some "common" for the task data - i.e. username, etc. Then, pass this logger as parameter to all methods you need. That way, you'll be able to set different filters and/or rules in your log4j config file. Or to scrape the output file based on the logger name.
EDIT: Also check MDC and NDC classes in log4j. You can add there context data.
In log4j you can log the thread name with the "%t" pattern. See log4j Pattern Layout.
In one of my (web) applications, i use a ThreadLocal logger that captures logging information into a StringBuilder. The logger object is initialized in the HttpServlet#service method, if a trace parameter is set (if it is not set, there is a very fast null-logger). The resulting output is either dumped as a HTML comment into the requesting page, or written to a log file in one segment.
In Java5 (and later) you can call
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
Inspect the stack trace to whatever depth you want and log accordingly.
In Java 1.4 you can get the same info with
StackTraceElement[] stackTrace = new Exception().getStackTrace();
You want to associate logger objects with threads I think. A ThreadLocal variable holding a log4j logger instance for each thread might help:
http://java.sun.com/javase/6/docs/api/java/lang/ThreadLocal.html
You will need to pass some structure to the data access layer that identifies the current "activity". You might already have an "Activity"-class that makes sense, you might use a Logger-instance as Sunny suggested or you might use a third structure to keep track of the activity-context.
In any case, since your "activity" is processed across multiple threads you cannot use thread-local-storage for keeping track of the current "activity", like most of the other current answers suggest. You will need to pass it around explicitly.
I would suggest making a small facade on top of log4j that expands the interface with methods like
void debug(Activity activity, String message);
and passing the activity-context into this from the data access layer.
You will need to make some modification to the data access layer to allow you to pass the current activity to it, but how best to do that depends strongly on the current interface.
If you use the Workspace-pattern, you might just need to add a setActivity() method on the Workspace-class, but other interface-pattern might require you to add an Activity parameter to all methods.
If you for some reason is unable or unwilling to change the data access layer, you might of course store the activity-context in thread-local-storage before invoking the data access layer and retrieve it just before spawning the sub-threads or enqueing the jobs in the data access layer. That is a workable solution, but is it a bit dangerous to pass information around in that way.
You can use MDC or NDC for your scenario, NDC works on principle of stack while MDC works on Map, here is official documentation for both
http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/MDC.html
http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/NDC.html

Categories

Resources