Usage of Static variables in Java Servlets (e.g. in AppEngine) - java

I have an application where Servlet has a method called Update(ReqIn, ReqOut). I call it from doGet & doPost and pass the Request and Response variables, and it is then up to Update(...) to fill out the following static variables:
...
public class Server extends HttpServlet {
public static HttpServletRequest In = null;
public static HttpServletResponse Out = null;
public static boolean isDebug = true;
public static boolean isPost = false;
public static String URL = "";
public static String IP = "0.0.0.0";
public static Cookie[] Cookies = null;
public static UserClass User = null;
public static boolean isLoggedIn = false;
...
}
Basically Abstracting most used stuff & updating it on every request. This also allows me to access IP address & current user data from anywhere in the website, by writting just Server.User.getUsername(); insead of making a new Class instance everytime a page is loaded and using much longer access code: Server.getUser().getUsername();
Now the question is: When in multi user environment (Jetty on AppEngine), can this introduce any problems? E.g. some threading/racing issues making user see incorrect IP address or in extreme case suddenly being logged in as different user?
Or should I rewrite code and change it to Public UserClass User instead of Public static UserClass User, etc?

Using statics is a hugely bad idea, since if you get two requests come in at the same time then they will write over each other. Take this trivial example to see what can go wrong:
1:public class Server extends HttpServlet {
2: public static int requestNo = 0;
3: public void doGet(HttpServletRequest req, HttpServletResponse resp)
4: {
5: requestNo++;
6: resp.getWriter().println(requestNo);
7: }
8:}
Now imagine the following timeline:
Request 1 comes in, and processes up to, and including, line 5.
Request 2 comes in, and processes completely.
Request 1 continues processing.
Both requests will get the text "2", instead of one getting "1" and one getting "2". This is a simple example of the state being stomped on.
Now, to answer the second part of your question;
Or should I rewrite code and change it to Public UserClass User instead of Public static UserClass User, etc?
No, that is also not good enough, since the J2EE spec allows the servlet container to use one instance of a class to service all of the requests for that servlet mapping, that is, the instance level variables will have exactly the same effect as being statics, they are shared between all requests.
This leaves only three real options:
Shove everything into HTTPSession. The problem here is that this is a map, so you lose type safety, and it is difficult to see where things are being used.
Create a Holder class to hold all of your state and pass that around everywhere. This is a little better, since at least you don't lose the type safety, but you still don't have full visibility either.
Pass the individual required items around.

Yes, this is a hugely bad idea!
What would you expect to happen if you got two requests at the same time? Each static variable can only hold one value, so you're going to lose data.
You could use ThreadLocal so that each thread only had access to the current request/user/etc that it was dealing with - but that's still basically a bad idea. It's brittle, and hides the fact that lower layers need the information. Pass the state down to the code that needs it instead.

Related

Java Jersey: Whats the best way to share data between the Main-object and the Webservice

Lets say I have a Jersey-service inside a grizzles server and I like to share data between the server and the service-implementation (e.g. mydata).
public class MyServer
{
String mydata="";
public static void main (String [] args)
{
ResourceConfig rc = new ResourceConfig ().packages (MyServer.class.getPackage ().getName ());
HttpServer hs = GrizzlyHttpServerFactory.createHttpServer (URI.create ("http://localhost/myserver"), rc);
for (int i = 0; i < 10; i ++)
{
mydata += "bla";
}
hs.shutdown ();
}
}
#Path ("myservice")
public class MyService
{
#GET
public String getIt()
{
// how to access mydata?
}
}
Whats the best way to share that data?
I can think of a singleton or make mydata static. But maybe there is a standard-way I do not see here?
Thanks!
You can make mydata static or instance variable of singleton if and only if mydata is really static and cannot be changed by multiple threads (e.g. inside your getIt() method of the service).
Such technique applies and uses usually for common configuration properties.
In general it is a standard way for such situation. BTW you can keep your mydata not necessary in the Server class, but make another class to keep such common data there (if there are bunch of them) , but it is a matter of choice.
Also it is more standard to do not make actual mydata field public , but provide getter/setter pair for it.
Finally, if such common/static value can be changed by multiple threads you need to make it synchronized to avoid concurrent modifications.
There are much more different approaches to handle concurrency and make code thread-safe, but it belongs to your actual needs. Anyway all of them end up to static/singleton synchronized implementation.
PS. Be careful, if it is a common static data you have to populate it before start the server not after (as in your example) - otherwise there is a possibility that request may come before data ready to use by service thread.

Call() is not public in android.telecom.Call, Cannot be accessed from outside package

I have the next class within SDK23 which should support playDtmfTone() :
import android.telecom.Call;
public class myDtmf {
public void myPlayDtmfTone() {
Call mytone = new Call(); // error here for Call()
mytone.playDtmfTone('0');
}
}
The Call() in the line 'Call mytone = new Call()' shows the error:
Call() is not public in android.telecom.Call, Cannot be accessed from outside package.
How can I make Call() public or make it accessible ?
Thank you very much.
In this specific case, referring to the Javadoc of Call:
[Call] Represents an ongoing phone call that the in-call app should present to the user.
So it doesn't really make sense to "create" an instance of it, since that requires you actually to create an actual phone call to some endpoint.
In general, if a method is not accessible outside the package, you aren't supposed to access it - it is not part of the API that the class developer has provided. There are ways to access it - specifically, reflection - but this is hacky and it is massively unlikely to be the way that you are meant to use the class.
The class may provide you with some other means to create an instance, like a static factory method (or an external factory) - but, for the reasons outlined above, that doesn't make sense in this case either.

design an error reporting utility

I had difficulties finding a relevant title since it is not a simple issue. I will try to explain. I have a class responsible of error reporting whose methods basically wrap multiple ways of reporting an error.
For example, I have a method failTest:
public static void failTest(Logger log, Exception e, String message, boolean reportToES, String esTestPath, String esTestSet, String esTestInstance)
{
log.error(e, message);
someExternalErrorReportingService(reportToES, esTestPath,esTestSet,esTestInstance);
Assert.fail(e,message);
}
And I call this error reporting method in many, many places and it doesn't seem a good practice (too many parameters, hard to follow their order etc.) to just call it with the es* parameters each and every time because they don't change very often so they could be set up once and then reused.
And I came up with this version
public static void failTest(Logger log, Exception e, String message)
{//same body
}
And then added method to set up es* parameters
setES(boolean reportToES, String esTestPath, String esTestSet, String esTestInstance)
{
this.reportToES = reportToES;
this.esTestPath = esTestPath;
this.esTestSet = esTestSet;
this.esTestInstance=esTestInstance;
}
and of course added these instance variables above.
And only now I can enunciate the issue:
now if I want to use this error reporting class I need to first instantiate it and set the es* fields. The issue is that I often need to use the error reporting in a utility class that could be static but now, with my change above, I have to instantiate it and set up the error reporting class in order to have the es* fields set before I call failTest().
To conclude, I don't like this solution either because I can't use static utility classes anymore and moreover some utility classes are already used in a static way so cannot be refactored to non-static and will end up being used sometimes static, sometimes instantiated.
So the question is, do you see a better solution in order to simplify the calling of failTest() in utility classes?
To give you an example, we have a client that
sets up the error reporting class and sets up its es* fields
This client calls utility method Utility.doSomething
public static doSomething(reportToES, esTestPath, esTestSet, esTestInstance)
{
try{
methodThatThrowsFatalException()
}
catch(Exception e){
failTest(log, e, "Some smart message",reportToES, esTestPath, esTestSet, esTestInstance);
}
}
Now, in order to reduce the number of parameters we can just add setErrorReportingInstance to the Utility class,
then in client instantiate the Utility, then utilityInstance. setErrorReportingInstance(configuredErrorReportingInstance). And doSomething becomes:
public static doSomethingRefactored()
{
try{
methodThatThrowsFatalException()
}
catch(Exception e){
errorReportingInstance.failTest(log, e, "Some smart message");
}
}
What is not ok, from my point of view, is that:
1. I have complicated the usage of Utility. Now I have to make sure it is instantiated before I use it. It's inconvenient when having a lot of Utility like classes.
2. I cannot make static methods in Utility if I have to do error reporting in their implementation.
3. The methods that are already used as static will remain with the es* parameters in their signature (due to backward compatibility). So I will have in the same class methods like doSomething and also methods like doSomethingRefactored.
4. I have created a dependency between utility classes and error reporting so I have an issue when I need to test the utility methods
The question is, how can I keep the simple design of utility classes as simple collection of static utility methods but in the same time use the error reporting class but without passing too many parameters since it is bad practice?
More details:
Actually the client is many TestNG test cases:
So first I had :
class TestClass1
{
static final boolean REPORT_TO_ES="true",
static final String ES_TEST_PATH="somePath", //and so on for the others
#Test
{
Utility1.doSomething(REPORT_TO_ES,ES_TEST_PATH,ES_TEST_SET,...
Utility2.doSomethingElse(REPORT_TO_ES,ES_TEST_PATH,ES_TEST_SET,...
Utility3.doSomethingMoreUseful(REPORT_TO_ES,ES_TEST_PATH,ES_TEST_SET,...
Utility4.doSomethingSomething(REPORT_TO_ES,ES_TEST_PATH,ES_TEST_SET,...
}
And then I would try to get rid of calling the doSomethings with the ES* values
by setting them once on the ErrorReporter instance (so I would also make ErrorReporter non-static).
class TestClass1
{
private ErrorReporter errorReporter = new ErrorReporter();
errorReporter.setReportToEs(true);
errorReporter.setEsTestPath("somePath");//and so on
Utility1 utility1Instance = new Utility1();
utility1Instance.setErrorReporter(errorReporter);
Utility2 utility1Instance = new Utility2();
utility2Instance.setErrorReporter(errorReporter);
#Test
{
utility1Instance.doSomething();
utility2Instance.doSomethingElse();
...
The title to your question should be "Static Mess".
Take a look at how real loggers work and you may get some ideas. Log4J and Slf4j are well respected ones. You need to control all of your static variables. You could create a Logger class that encapsulates the ES data and does the real work of logging:
// Does the real work of logging.
class Logger {
public Logger(all of your es data)
public fail(String msg) // Logs msg
}
Then you need a static collection of these Loggers referenced by name (I assume you have more than one set of es data). This gives you a central place to go get the loggers. Works if you're in a static method or somewhere else. The static collection goes inside the LogFactory object
class LogFactory {
private static Map<String, Logger> loggers ...
public static Logger get(String name) ...
}
Here is your static method using the new logger:
public static doSomething() {
try {
methodThatThrowsFatalException()
}
catch(Exception e){
LogFactory.get("Util").failTest(e, "Some smart message");
}
}
I would add a clear or reset method to LogFactory so that you have a chance of writing JUnit tests for your code. For the same reason I would write a NullLogger (in which case you might want to pull out an interface that the NullLogger and the EsLogger can both implement.
You need to decide how to add Loggers to LogFactory. I suggest doing it in your main class. Resist the temptation to do it in a static initializer.
LogFactory could also be written so it holds a collection and not a static collection. You then just keep a static reference (a Singleton) to it. Just keep in mind that you'll want a way to clear the Singleton to make unit testing possible.
Good luck.

How to avoid concurrent access of controller method with the same session in java spring?

I would like to know how to make sure that some method in a service is accessed only once at a time per session.
I'll illustrate by a small example:
Assume we have a user in a state A (user.state = A). This user sends a HTTP GET request to our java spring controller to get a page, say /hello. Based on his status, he will be sent to either A or B. Before that, we will change his status to B (see code below).
Now, assume again that the call dao.doSomething(); takes a lot of time. If the user sends another GET (by refreshing his browser for instance), he will call the exact same method dao.doSomething(), resulting in 2 calls.
How can you avoid that?
What happens if you sends 2 HTTP GETs at the same time?
How can you have something consistent in your controller/service/model/database?
Note 1: here we don't issue the 2 HTTP GETs from different browser. We just make them at the same time on the same browser (I'm aware of the max concurrent session solution, but this does not solve my problem.).
Note 2: the solution should not block concurrent accesses of the controller for different users.
I've read a bit about transaction on service, but I'm not sure if this is the solution. I've also read a bit on concurrency, but I still don't understand how to use it here.
I would greatly appreciate your help! Thanks!
code example:
#Controller
public class UserController {
#RequestMapping(value='/hello')
public String viewHelloPage() {
// we get the user from a session attribute
if (user.getState() = A) {
user.setStatus(B);
return "pageA";
}
return "pageB";
}
#Service
public class UserService {
Dao dao;
#Override
public void setStatus(User user) {
dao.doSomething();
user.setStatus(B);
}
}
Although I wouldn't recommend it (as it basically blocks all other calls from the same user to). On most HandlerAdapter implementations you can set the property synchronizeOnSession by default this is false allowing for concurrent requests to come from the same client. When you set this property to true requests will be queued for that client.
How to set it depends on your configuration of the HandlerAdapter.
how to make sure that some method in a service is accessed only once
at a time per session.
Try to Lock on session object in your controller before calling service method
If dao.doSomething() is doing work that you only want to happen once, you should use an idempotent method like PUT or DELETE. There's no law forcing you to use the correct method, but worst-case it's a self-documenting way to tell the world about how your API should be used. If that isn't enough for you, most browsers will try to help you out based on the type of request. For instance, the browser will often use caching to avoid multiple GETs.
It seems like what you really want to know is how to enforce idempotency. This is very application-specific. One general approach is to generate and store a pseudo-unique id on the server side for the client to attach to their request. This way, any request with the same id after the first can be safely ignored. Obviously old ids should be evicted intelligently.
As I said, the solution is often application-specific. In your case above, it looks like you're trying to switch between 2 states, and your implementation is a server-side toggle. You can utilize the client to ensure that multiple requests will not be a problem.
#RequestMapping(value="/hello", method=RequestMethod.PUT)
public String test(#RequestParam("state") String state) {
dao.setState(user, state)
switch (state) {
case "A":
return "B";
case "B":
return "A";
default:
return "error";
}
}
If you don't mind to configure and use AOP, then the following might help you
#Aspect
#Component
public class NonConcurrentAspect implements HttpSessionListener{
private Map<HttpSession, Map<Method, Object>> mutexes = new ConcurrentHashMap<HttpSession, Map<Method, Object>>();
#Around(value = "#annotation(org.springframework.web.bind.annotation.RequestMapping)")
public Object handle(ProceedingJoinPoint pjp) throws Throwable {
MethodInvocationProceedingJoinPoint methodPjp = (MethodInvocationProceedingJoinPoint) pjp;
Method method = ((MethodSignature) methodPjp.getSignature()).getMethod();
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest();
HttpSession session = request.getSession(false);
Object mutex = getMutex(session, method);
synchronized (mutex) {
return pjp.proceed();
}
}
private Object getMutex(HttpSession session, Method method) {
Map<Method, Object> sessionMutexes = mutexes.get(session);
Object mutex = new Object();
Object existingMutex = sessionMutexes.putIfAbsent(method, mutex);
return existingMutex == null ? mutex : existingMutex;
}
#Override
public void sessionCreated(HttpSessionEvent se) {
mutexes.put(se.getSession(), new ConcurrentHashMap<Method, Object>());
}
#Override
public void sessionDestroyed(HttpSessionEvent se) {
mutexes.remove(se.getSession());
}
}
It synchronizes on a per-session per-method mutex. One restriction is that the methods so advised should not call each other (which is hardly a case, unless you violate MVC design pattern severely), otherwise you may face deadlocks.
This would handle all the methods tagged with #RequestMapping, but if you want just few methods be guarded against concurrent execution,
then, as one of the possible solutions, you could introduce your own annotation, e.g.
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
#Documented
public #interface NonConcurrent {
}
tag the specific methods with this annotation, and replace #RequestMapping in #Around annotation in the above aspect class with your own.
In highly contended environment you may think of more advanced solution than intrinsic locks.
I would, however, advise against using HandlerAdapter's synchronizeOnSession option, not only because it synchronizes all the invocations on the same mutex, but, which is less obvious, the synchronization on publicly available mutex is potentially dangerous.

Single class with multiple constructor parameter values or many classes?

I have a class Response which contains a HTTP response with a HTTP status code like 200 or 404 and few other things like a view name and a domain object. But lets focus on the status code. I could use a single class and pass the status as a parameter:
public class Response {
private int status;
public Response(int status) {
this.status = status;
}
}
// in a handler method:
return new Response(HttpStatus.OK);
The other way would be to create a new class for every status code (41 status codes in HTTP 1.1). Like this:
public class Ok extends Response {
public Ok() {
super(HttpStatus.OK);
}
}
// in a handler method:
return new Ok();
public class Created extends Response {
public Created() {
super(HttpStatus.CREATED);
}
}
// in a handler method:
return new Created();
In reality there will be usually more parameters like the view name and the domain object, like this new Response(HttpStatus.OK, "customer", customer) respective new Ok("customer", customer).
my recommendation
1) if there is no behavior associated with each status code then there is no need for new abstractions.
2) use enums for constants instead of int
The "pure" way would be to have a type for each distinct value, but in practice this may be overkill.
Generally speaking, consider whether:
There is any unique processing (which would lend itself to classes)
Whether there could be a hierarchy between the entities (e.g., statuses representing success and statuses representing errors).
In my experience, if there are hierarchies in the domain, they often end up in the code. You could save future refactoring by planning around that. For instance, error statuses may later also have things like error details tacked on.
My rule of thumb is to look at the specification in which the magic numbers appear. If they are each associated with a lot of details, that could indicate future problems if I merely keep them as ints, since I am essentially using a key to a more complex entity.
Also, when taking details from a fixed domain, an enum might be better than direct int.
Ask yourself - do you need different "types" for each status code? It could be useful if for example you want to use a specific type say OK as the parameter to some method. If not, I don't see any benefits of the second approach. Go for the first one.
I would keep the constructor simple. Something like:
public Response(int status)
public Response(int status, String reasonPhrase)
public Response(int status, Map<String,String> headers)
public Response(int status, String reasonPhrase, Map<String,String> headers)
Or, possibly, omit the last 2 and provide a setHeader(String, String)

Categories

Resources