I want to create a Servlet that processes input to a serial device and for that reason I want to make sure that exactly one instance of Servlet exists in the container at a time (irrespective of whether the container makes only one instance I have to make sure of it) and also the access to the serial port is either synchronised or serialised.
Any suggestions?
You don't need the servlet to be a singleton, you only need to be able to control access to the serial port. In fact even if you could enforce a single instance of the servlet class, the spec enables multiple users to access the servlet concurrently.
You could instead write a class that handles access to the port, encapsulating control by only allowing a single thread to access at a time. You'd then need to decide how you wanted concurrent requests to the servlet to behave (block, return some sort of 'serial port in use' error message, etc).
Suggestion: don't do that. Leave servlet management to the container, and use your own singleton for serial port processing.
Solution: you cannot, as you have no control over constructor. What you can do, though, (and what is a Very Bad Thing—don't tell anyone I said that) is to have a static field in a servlet, keeping a reference to the first instantiated instance. This way, all the instances of the servlet will be able to delegate the processing to this very first instance.
Again, just separating request processing from serial port processing will make things much more easier for both you and the container.
Related
I'm making calls to the Java backend through servlets and for each call to the API im using i need to supply password and username. Can I save the users password/username in a variable so I can use it every time the user makes a call to the API?
Or will the variable be overwritten if there are multiple users?
The overall question perhaps is: Does every user get new "fresh" servlets or is the data saved from the users before?
Servlets are shared for performance reasons, so they should be stateless (or thread-safe, but then you'd just be reinventing the wheel). If you need to keep state with a user, put it into HttpSession.
If you use static variables then the variables got shared across the users. Also, it's a concurrency issue and you need to handle it. If the variables are not static then each user would have an excluded instance.
Anyway, If you want to store some information and you want to retrieve them in the future when a specific user call the servlet then it's common to use HttpSession. Also, consider that you need to grab the http cookie in your client and send it to the server for the further calls.
Also, it's a common scenario that server provides an API key for each client. Then whenever the client wants to call an API; it's necessary to send the key through a specific http header.
The above scenario would have some security issues if you don't use a secure connection like HTTPS between server and clients.
Does every user get new "fresh" servlets or is the data saved from the
users before?
Servlet instance will be created only once (unless you are doing something differently like using SingleThreadModel) & maintained by the container (like Tomcat, etc..), i.e., one single servlet instance is going to be used/shared by all requests.
So, don't use the servlet's instance variables to store any data.
Can I save the users password/username in a variable so I can use it
every time the user makes a call to the API?
You shouldn't be saving userids and passwords into JVM (RAM) memory because you will loose all of the data when the JVM shuts down, so you need to use some persistent store like a database (prefer this) or file system.
I have an interesting problem.
We have a number of EJB's that are called both by local code (via local interface) and by client code (via remote interface).
The code runs on Weblogic 12c servers and use RMI for method invocations.
The system is in development already for many years, and along others implements browser functionality around user defined cursors (a kind of handle for a result set). There are already many calls to obtain such a cursor for various data types.
When the cursor is obtained it is used subsequently to request the underlying data (another call).
In our case we want to know whether the call is done from local code or from a remote client. We want to know this so we can preload the first n items, and thus reduce the number of calls to our server. Each call has an overhead of about 20ms, which we want to avoid.
The remote client code is generic (the cursor is wrapped in a kind of list) and could easily be adjusted to handle the preloaded data.
The local callers also call these EJB methods to obtain a cursor, but usually use other functionality to handle the cursor (wrapping in iterators, joins, etc). So they would become a lot more complex if they had to handle the preloading (and they often do not need it).
So we want to make an interceptor to do preloading of data in the cursor, but only if the call is made from a remote client. So far we could not find a way of doing so.
I tried RemoteServer.getClientHost() but it always throws the exception there is no connection.
I searched if the SessionContext could be extended with a field/value to be set by the caller to identify the remote client, but could find anything about doing this. (We have a homemade wrapper for the service interface which could be extended of inserting such information in a context).
So the question is:
Is there a generic way to find out in an EJB interceptor that the origin of the call was from a different system
If the remote client uses any kind of authentication there should be some info in the security context about the principal which can be used to differentiate. Otherwise, before finding a better solution new Throwable().getStackTrace() returns an array of all callers. There must be a method upstream that could tell if the call is local or it's been done via remote call.
we have a JavaEE Web application that runs on Tomcat5 server (jsp, java and extjs are used on development of this tool).
We observe sometimes, particularly when the application is highly used, that some session variables or interface fields are mixed up in servlets.
This means that : when one user connects, his parameters are kept in the sessions.
After an update or insertion of data in the database ORACLE,the system returns the name of another user who was probably connected at the same time on a different navigator or a different computer.
Others times the request.getparameter gets a values from different clients or user interfaces.
Thank you to help me fix this problem.
The only way for this to happen is if you have a singleton somewhere that keeps track of the session and for some reason this singleton is mixing up the variables between sessions.
You can try this: Instead of differentiating a user only by its credentials (assuming you are not using Federation), return a token, unique amongst all sessions to the user logging in, and make the user send that unique id with every request. This way you will be able to differentiate the request/responses even if the user logs in using many different browsers.
But again, this will only happen when you do something like having a singleton connecting the session, by itself the session would not exchange variables amongst them.
I've finally understood how servlet.java works.
I works like main process that create a thread for any call
thus, all attributes of such class are common to all thread and we are not sure of the result that we get when accessing them.
If we want any client to use those variables in a private context, we must put them in the function "doGet" or "doPost" as local variables.
My problem have them been solved
I have a global variable called loginAttempt in a servlet class. What will happen to this global variable if two requests hit on the same time?What will happen is an unforeseeable event.
Is having global variables in servlet an evil ??
If i put the loginAttempt is side doPost() its initializing each time.
Yes.
Your variable is readable/writeable by any other class. You have no control to ensure that they all do sensible things with it. One of them could overwrite it/incorrectly increment it, etc
The is one instance of a servlet, per JVM. So may threads may try to access it concurrently. Because it is global, and you are not providing any synchronization/access control, it will not be thread-safe. Also, if you ever run the servlet in some kind of cluster with different JVMs, then the variable will not be shared between them and you will have multiple loginAttempt variables.
If you have to have it in the servlet, make it static but do not make it public. Provide getters/setters to access and update it. Learn about thread-safe programming so that multiple-threads can update it and read it safely.
Much better, store it in the servlet-context. This should be where you store servlet-wide data like this.
They are not evil as long as you understand that there is generally only a single instance of a servlet created and the global variable will be shared by all clients of that servlet - that is every request, on different threads at the same time and by multiple users at the same time.
I am guessing that your global variable loginAttempt is counting the number of login attempts then as long as this is done in a thread safe way it would be a reasonable way of counting the number of login attempts made on this servlet. This would be for all users though. If you want login attempts per user then you probably need to create a session and use the session context to store this sort of info.
Store it as a session attribute. Otherwise the global variable concept will screw you up totally.
Using session is a good idea as it's
1) If the web service is restarted, the session data is not lost
2) In a load balanced environment, the session data is stored in a central location, meaning any server can serve the request and have access to the session data.
So it's accessible yet it's hidden.
In a large number of concurrent access,You may want to pay attention to the thread safety problem of Servlet...and you can try the following methods to avoid this problem...
1、
public class loginAttempt extends HttpServlet implements SingleThreadModel {
...
}
2、
The second method:
Use the synchronized keyword
3、
Avoid the use of global variable
YES.
Global variables are shared with everyone
It depends, if your variable is read-only, it should be fine. But in most cases, global variables are evil. I can't give you a solution because I don't have your code but I am sure there is an alternative way.
In your usecase, it is beyond evil. loginAttempt will be shared by all threads accessing the servlet
First of all there is no terminology called global variable in Java. They are called class variable or instance variable.
Second, Yes its bad practice to have instance variable in the Servlet if you are assigning request or session scoped data as it will be shared by all threads.
You can use it for application-wide values, most often obtained from context parameters. or If the data never changes (immutable) like Constants.
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.