How to access the session from a Java class - java

I need to write a small Java class that will enable me to add to and read from the current user session.
Everything I see refers to Servlets but I'd ideally like to just use a plain old class.
Can anyone please help this Java Newbie?
Thanks

The general concept of a "Session" is really just a data storage for an interaction between a HTTP client and server. Session management is automatically handled by all HTTP Servlets. What framework?
If you're just wanting to store information for a console app to remember information between runs, then consider using Xml to save/load data from a file.

Use a component based MVC framework which abstracts all the ugly Servlet API details away so that you ends up with zero javax.servlet imports. Examples of such are JSF2 and Struts2.
In JSF2 for example, you'd just declare User class as a session scoped managed bean:
#ManagedBean
#SessionScoped
public class User {
// ...
}
Then in the "action" bean which you're using to processing the form submit, reference it as managed property:
#ManagedBean
#RequestScoped
public class SomeFormBean {
#ManagedProperty(value="#{user}")
private User user;
public void submit() {
SomeData someData = user.getSomeData();
// ...
}
}
That's it.
If you'd like to stick to raw Servlet API, then you've to live with the fact that you have to pass the raw HttpServletRequest/HttpServletResponse objects around. Best what you can do is to homegrow some abstraction around it (but then you end up like what JSF2/Struts2 are already doing, so why would you homegrow -unless for hobby/self-learning purposes :) ).

Yes, just pass the HttpRequest to your class from your servlet.
In your servlet do something like this,
cmd.execute(request);
In your class do something like this,
public class Command implements ICommand {
.
.
public void execute(HttpServletRequest request){
HttpSession sess = request.getSession(false);
}
.
.
.
}

In general, as mentioned in the other answers, session in many ways acts as a store. So to interact wth a session from another class which is outside of the Servlet/JSP framework the reference to the session in question needs to be procured. There are few ways it can be achieved:
1) Passing the session as part of a method parameter (already mentioned in other answers)
2) Binding the session to a thread local variable on to the current thread executing (refer ThreadLocal). This method has the advantage of not declaring specific parameters on the method signature of the class that needs to use the session. In addition, if the calling thread goes through a library and then again calls some specific class e.g. Servlet->YourClass0 -> Apache Some Library -> YourClass1, the session will also be available to YourClass1.
However, the thread local also needs to be cleared when the executing thread returns through the initial component (servlet let's say) otherwise there certainly could be memory leaks.
In addition, please refer to your specific framework for treatement of sessions, the above mechanism works fine in Tomcat.

Related

Guice Request Scope for tracing workflow of request

I have a use case where I have 6 steps being performed in one request. The business is requesting that we capture metrics on what the result of each step was in the process. They want us to log to a Kinesis stream.
Architecturally I am looking at the best solution. We have java based services I want to have a request scoped object enriched as the request progresses, then when the endpoint finishes we would make a service call to kinesis asynchronous using a fire and forget pattern. This way the reporting is not holding up the main thread.
I was looking at using the raw ThreadLocal or guice scope. Has anyone ran into to a similar problem that they solved? Im thinking of use guice request scoped components, which will greatly simply the code. Just looking for some opinions. Thanks!
I'm assuming you aren't on a servlet environment because, then, you will just use the built in request scope. Even then you can use the request scope from guice-servlet building the scope yourself.
void processRequest() {
RequestScoper scope = ServletScopes.scopeRequest(Collections.emptyMap());
try ( RequestScoper.CloseableScope ignored = scope.open() ) {
step1();
step2();
step3();
step4();
step5();
step6();
}
}
You can use #RequestScoped and it will be the same object on all your steps. You can, for example, use a provider to get access to it.

Dynamic URL from database and MVC in JSP

I am learning JAVA and Spring Framework. I wanted to know that is it possible in java to create Dynamic URL in spring framework using values from url and fetching from database.
I am trying to make URL Shortner in Java and I will need to lookup for url's short code in my database and as we all know, url shortner will look like "url/ShorTCode" and my script will look for "ShorTCode" keyword in database and will redirect to associated weblink.
So I wanted to know that is it even possible in JAVA and Spring? And one more thing, if I make something like this "url/yt/VIdeoCode" or "url/fb/UserProfile"
So it will look at yt object which will redirect to youtube link only and fb object which will redirect to facebook user profile.
I want to clarify that I am still learning JAVA, JSP and Spring but I want to keep this thing in my mind while I am learning so I can focus on some particular things.
Thank you all fro helping me.
If you're asking how your controller could respond with a dynamic redirect, the answer is either:
(1) Have the controller return a "redirect:" result instead of view name. It must be followed with an absolute url, and behavior might depend on your spring version and configuration, but basically it looks like this:
#RequestMapping(...)
public String myMethod(){
String url=... // database lookup, e.g. "http://myUrl"
return "redirect:"+url;
}
(2) Less elegant but sometimes useful: get direct access to the response. If your controller method has a parameter of type HttpServletResponse spring will automatically inject it. So:
#RequestMapping(...)
public String myMethod(HttpServletResponse resp){
...
response.sendRedirect(...)
}

More than one user in the same Controller Spring MVC

I'm starting to develop for Web and I'm using Spring MVC as my Server Framework. Now I'm wondering about creating variables in Controller class. I had to do it to manage some data in server, but now I'm concerned about the following case: If I have more than one user sending information to the same page, at the same time, would one user interfere on another user variable?
Here's some code example:
#Controller
public Class myController {
int number;
#RequestMapping("/userInformation")
public String getInformation(int info) {
number = info;
}
public void doSomethingWithIt() {
number = number + 1;
}
}
In this case, If I have more than one user sending data to /userInformation at the same time, would Spring MVC create one Controller for each user? This way I wouldn't have problem, I guess. But if not, I have to rethink this implementation, don't I?
You are right. Controllers are singletons and must be stateless. Server side state belongs in session or in a data store. You can also use a request scoped object (look at bean scopes in spring).
The Spring container will create one instance of your Controller. So all users will share that instance.
If you have data that is private to a user, you have several options:
store it in the HTTP session (not recommended if it's a lot of data, as your memory usage might explode)
store it in a database and retrieve it upon each request, based on some property identifying the user
store it in a memory cache and retrieve it upon each request, based on some property identifying the user
Option 3 is the most simple one of them, you can even implement it as a Map<User, UserData> instance variable on your Controller if you like. It's not the cleanest, most beautiful or most secure option, just the most simple.
You should not use any instance variables in the Spring Controller that represent state of the controller class. It should not have state since its single instance. Instead you could have references to the injected managed beans.

Sharing a static object between a servlet and a webservice

I have a servlet which handles http get requests that I'd like to be able to share an object which is also used by a webservice im developing. They are both on the same tomcat server within the same web-app container. Im not sure best how to do it any ideas ?
You can share things across the webapp by storing them as attributes in the ServletContext (using setAttribute / getAttribute). You could create the object in an impelementation of ServletContextListener, store it in the ServletContext, and then retrieve it and use it from your web service and servlet.
I will expand on my comment here.
In the simplest case ServletContext.setAttribute/getAttribute would be fine. But some people rightly raised the questions about thread safety.
For this a better approach would be to store a shared POJO in a ServletContext during webapp initialization and get it wherever you need with ServletContext.getAttribute.
For this you need to implement ServletContextListener interface and declare it in your web.xml file.
<listener>
<listener-class>your.package.ServletContextListenerImpl</listener-class>
</listener>
This listener is called once when your webapp is loaded by the servlet container, and when it is about to be unloaded by the servlet container. In both cases it passes ServletContextEvent that has a handle to ServletContext. It is at that point that you want to set/removeAttribute that points to your shared object.
Because of this you may be certain that ServletContext.getAttribute will return a valid object when called from the Servlet.service or one of the do... methods.
As for attribute name, I would go with your Shared class classname. I would also add a static access method to your shared class to get it from the ServletContext, like this:
public class Shared
{
...
public static Shared fromServletContext ( final ServletContext context )
{
return (Shared) context.getAttribute( Shared.class.getName( ) );
}
}
The simplest option is create a Singleton - a class which allows only one instance in memory. Since you get it by calling a static method on the class itself it should be available to both the servlet and the WS
If my alternative understanding of the question is correct, the data which comes from request should be stored, and then retreived by the web-service. If this is supposed to run in a multi-user environment, you might consider using an in-memory database (HSQLDB) to temporarily store the data. Then you will be able to retrieve it with your web-service, based on some criteria I cannot foretell.
If this is application-specific data (accessible by all users (sessions)), then use ServletContext#set/getAttribute(). If this is user (session)-specific data, then use HttpSession#set/getAttribute().
Let the servlet class set the object in the desired scope (application or session) by a specific attribute key and let the webservice get the object from the desired scope by the same attribute key.
I think you rather need the HttpSession.
The singleton story makes no sense here.

What would be the best way to match up two object instances between two different applications in a J2EE server?

I have a J2ee application where I basically want two objects, created by two separate servlets to communicate directly and I need these intances to be stable, i.e. to "know" each other during the session.
The sequence is roughly:
Client sends a request to Servlet #1, which creates object A
Client sends a second request (after the first returns) to servlet #2 which creates object B.
Object B finds A, using JNDI, and the two objects interact.
The client now continues to send requests to object A which needs to find B again.
How do I make sure that these two instances know each throughout the session?
Binding them to JNDI doesn't entirely solve the problem, since object B needs to communicate with its original servlet (servlet #2), which is not kept stable across requests.
Any ideas?
Thanks in advance.
Yes, I admit the problem description is a bit vague. But it's not a very simple application.
Still, I will try to ask it better:
My end goal is to create a sort of a "semantic debugger" for my application that, as opposed to a java debugger which simply debugs the java statements.
The application debugged is basically a servlet. which my tool connects to.
The tool maintains a connection to the application through another servlet which controls the debugging process.
These two servlets need to communicate with each other constantly and directly.
My current thought is to set up a stateful session bean that will facilitate this communication (never done it, still struggling with setting it up).
But I would appreciate any thoughts on how to achieve this better.
And what stops you from using the Session? You don't need JNDI, just place your object into session under a predefined name. If the communication object is application-wide, use Singleton.
P.S. It looks to me you're doing something weird, while the solution could in fact be simpler. Can you describe the task, not the proposed implementation? What is a "semantic debugger" anyway?
To be honest: I don't fully understand what you are trying to achieve.
Can you perhaps try to explain the problem you are trying to solve instead of the solution?
What do these objects depend on? Are they user specific? Then put them into the session and you can retrieve them from the session again (request.getSession().getAttribute("A")).
Are they global for all users? In that case put them into a spring configuration and retrieve them from there.
Never store any information inside the servlet.
EDIT:
ok, so from what I understand storing the values in the session is imho the best way to solve this problem (in "Java-Pseudo-Code"):
public class BusinessServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse res) {
HttpSession session = req.getSession(true);
BusinessCode business = session.getAttribute("A");
if (business == null) {
business = new BusinessCode();
session.setAttribute("A", business);
}
DebugObject debug = session.getAttribute("B");
if (debug == null) {
debug = new DebugObject();
session.setAttribute("B", debug);
}
business.doSomeWork(debug);
}
}
public class DebugServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse res) {
HttpSession session = req.getSession(true);
DebugObject debug = session.getAttribute("B");
if (debug != null) {
debug.printDebugMessages(res);
}
}
}
Does this help?

Categories