Trying to retrieve HttpSession object - java

For some background, I'm using JBoss AS 7 with EJB. I'm sending a message to my server from the client using errai message bus when it initially connects to retrieve its session ID so that I can make requests from it later on and have the server respond to the specific client.
How do I go about doing this? Can I inject a HttpSession object server side somehow? I'm very new to this so please bear with me. If I'm too vague let me know and I'll try to elaborate more.

If you are sending a message to an ErraiBus service method, you will have the Message object available. You can retrieve the session from it and get that session's ID like this:
#Service
public class ClientHelloService implements MessageCallback {
#Override
public void callback(final Message message) {
HttpSession session = message.getResource(
HttpServletRequest.class, HttpServletRequest.class.getName()).getSession();
System.out.println("Client said hello. Session ID: " + session.getId());
}
}
If you are instead sending the message to an Errai RPC endpoint, you will not have such easy access to the message. In this case, you will have to use the RpcContext.getSession() method:
#Service
public class ClientHelloRpcServiceImpl implements ClientHelloRpcService {
#Override
public void hello() {
HttpSession session = RpcContext.getHttpSession();
System.out.println("Client said hello. Session ID: " + session.getId());
}
}
The way this works is simple but ugly: RpcContext class stores the Message object that contained the RPC request in a ThreadLocal, and it just retrieves the HttpSession from that.

// the following variable is in the Http servlet service() method arguments
// only shown here this way to demonstrate the process
javax.servlet.http.HttpServletRequest serviceRequest;
javax.servlet.http.HttpServletResponse serviceResp; // addCookie()
javax.servlet.http.HttpSession cecil;
javax.servlet.http.Cookie[] reqCk;
// "(boolean overload) "true" creates the session" or call the other overload version method with no argument
// to retrieve the session getSession() "the server container stores and creates sessions"
// false in that version is to avoid bothering for a session to cut down uneeded processing
cecil = serviceRequest.getSession();//creates a session if it does not have one
String httpSession_ID = cecil.getID();
if((reqCk = serviceRequest.getCookies()) == null){
// perhaps create a cookie here using "new class "
// cookiePiece = new javax.servlet.http.Cookie("COOKIENAME",....); ....YOU MUST LEARN THE COOKIE PARTS WRITING RULES FOR BROWSER COOKIES !!! ; ; ;
serviceResp.addCookie(cookiePiece); // now is on the servers array "reqCk"
}else{
// process the cookie here using javax.servlet.http.Cookie methods
}
Other ways of storing and retrieving data are session scoped JSP or JSF beans.

Related

send client info to ejbs

I need to add certain functionality to an existing ejb projects.
Specifically - the client info, such as IP addres, login credentials (who is connected) and client application name
My bean is a stateless, so I worry there is an issue with such an approach..
My client code currently has the following:
private static MySession getmySession() throws RemoteException {
if(mySession != null) return mySession; //mySession is a private variable
try {
Properties h = new Properties();
h.put(Context.INITIAL_CONTEXT_FACTORY, contextFactory);
h.put(Context.PROVIDER_URL, serverUrl ); //t3://localhost
InitialContext ctx = new InitialContext(h);
mySessionHome home = (mySessionHome) ctx.lookup( "mySessionEJB" );
mySession = home.create();
return mySession;
} catch(NamingException ne) {
throw new RemoteException(ne.getMessage());
} catch(CreateException ce) {
throw new RemoteException(ce.getMessage());
}
}
Ideally, I would like my 'mySession' know about the client at the point it is returned.
If that may not be possible,
I would like to send a client info at the time a particular method of MySession is called.
Somewhere in this code
public static List getAllMembers() throws RemoteException, CatalogException
{
getMySession();
List list = mySession.getAllMembers() );
return list;
}
There are quite many such methods, so this is less desirable. but I will take it if it solves the task.
At the end of the day, when "getAllMembers()" executes on the server, I want to know particular info of which client has called it. (there can be many different, including webservices)
Thanks
First thing - what are you doing with the client information? If you're planning to use it for auditing, this sounds like a perfect use for Interceptors!
The EJB way to access user information is via the user's Principal, and there's no problem using this in a stateless bean. You may find that this doesn't get all the information you would like - this answer suggests getting the user IP isn't entirely supported.

apache tomcat 8 websocket origin and client address

H.e.l.l.o community, i hope someone can help me ... i am using apache tomcat 8.0.0-RC5 and JSR-356 web socket API ...
I have 2 questions:
1) Is it possible to get the client ip on #OnOpen method ??
2) Is it possible to get the origin of the connection ???
I followed the websocket example which comes with the distribution of tomcat and i was not able to find the answers .... My java class is basically as follow
#ServerEndpoint(value = "/data.socket")
public class MyWebSocket {
#OnOpen
public void onOpen(Session session) {
// Here is where i need the origin and remote client address
}
#OnClose
public void onClose() {
// disconnection handling
}
#OnMessage
public void onMessage(String message) {
// message handling
}
#OnError
public void onError(Session session, Throwable throwable) {
// Error handling
}
}
Repeating the answer I already gave you on the Tomcat users mailing list...
Client IP. No. Generally this type of information is available at the handshake
which occurs before OnOpen but client IP is not one of the pieces of
information exposed. You might be better blocking these earlier e.g. with iptables or similar.
Origin. ServerEndpointConfig.Configurator.checkOrigin(String) You'll need a custom Configurator. Keep in mind that a malicious client can forge the origin header.
I know this question is old, but just in case someone else finds it in a web search:
Yes there is an easy workaround. A Servlet can receive and forward a WebSocket upgrade request. The trick is to get the client IP address and expose it as a parameter.
Here's your servlet code:
#WebServlet("/myExternalEntryPoint")
public class WebSocketServlet extends HttpServlet {
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
var dispatcher = getServletContext().getRequestDispatcher("/myInternalEntryPoint");
var requestWrapper = new MyRequestWrapper(request);
dispatcher.forward(requestWrapper, response);
}
}
And here's MyRequestWrapper:
class MyRequestWrapper extends HttpServletRequestWrapper {
public RequestWrapper(HttpServletRequest request) {
super(request);
}
public Map<String, String[]> getParameterMap() {
return Collections.singletonMap("remoteAddr", new String[] {getRequest().getRemoteAddr()});
}
}
Now in your WebSocket implementation, you'll be able to get remoteAddr via javax.websocket.Session.getRequestParameterMap().
Naturally, if your original request has parameters that you care about, you'll need to create a map that includes those as well. Also I recommend you append a separate, secret parameter and check for it in your WebSocket code to prevent anyone from hitting the internal entry point directly.
I figured out this was possible because of this thoughtful comment in the Tomcat source code (WsFilter.java):
// No endpoint registered for the requested path. Let the
// application handle it (it might redirect or forward for example)

GWT Request Factory - Create and persist object - Should proxy automatically be populated with id?

If i create a proxy object on the client side and persist it, shouldn't my proxy object after it is persisted on the server side be automatically updated with the generated id?
For example this code prints out "null".
final MyRequestFactory requestFactory = clientFactory.getRequestFactory();
final TestRequest request = requestFactory.testRequest();
final TestProxy myTestObj = request.create(TestProxy.class);
Request<Void> createReq = request.persist.using(myTestObj);
createReq.fire(new Receiver<Void>() {
#Override
public void onSuccess(Void nothing) {
System.out.println(myTestObj.getId());
}
});
Or do i have to change my code so that the persist method returns my object again?
Yes, you are right, calling persist() does not change the proxy object in the client, you have to go to the server to get the object again.
The normal way is to define a persistAndReturnSelf() method in your Request.
request.persistAndReturnSelf(myTestObj).fire(new Receiver<TestProxy>()) {
...
}

How to run a thread from struts2

i am developing a sturts2 webapplication, i am having a login page with username and password fields. As soon as user submitted form with values , i am validaing the login, if the user provides valid username and passoword, it is redirected to home page. While redirecting the home page, i have to call a thread in which i sets some data in session for future use. How to do this ?
What i did is
import com.opensymphony.xwork2.ActionContext;
if( loginSuccess(userInfo) ) {
initializeDatas(); // calling thread after userInfo bean validated
// redirecting to home page
return HOME_PAGE;
}
I have added a new class which implements runnable.
class intilalizer implements Runnable {
#Override
public void run() {
try {
System.out.println("Started to set values ");
List<String> iphoneSdks = new ArrayList<String>();
List<String> iphoneOSSdks = IosSdkUtil.getMacSdks(MacSdkType.iphoneos);
List<String> simSdks = IosSdkUtil.getMacSdks(MacSdkType.iphonesimulator);
List<String> macSdks = IosSdkUtil.getMacSdks(MacSdkType.macosx);
iphoneSdks.addAll(iphoneOSSdks);
iphoneSdks.addAll(simSdks);
iphoneSdks.addAll(macSdks);
ActionContext context = ActionContext.getContext();
System.out.println("context ===> " + context); // here i am getting null value
String httpRequest = ServletActionContext.HTTP_REQUEST;
System.out.println("httpRequest =====> " + httpRequest);
Object object = context.get(httpRequest);
System.out.println(object);
HttpServletRequest req = (HttpServletRequest) object;
req.setAttribute(REQ_IPHONE_SDKS, iphoneSdks);
req.setAttribute(REQ_IPHONE_SIMULATOR_SDKS, simSdks);
System.out.println("Value initialized####");
} catch (Exception e) {
e.printStackTrace();
}
}
}
I am getting
java.lang.NullPointerException
at com.photon.phresco.framework.actions.intilalizer.run(Login.java:286)
at java.lang.Thread.run(Thread.java:680)
I am getting this error on line .
ActionContext context = ActionContext.getContext();
System.out.println("context ===> " + context); // here i am getting null value
From Struts 2 JavaDoc
The ActionContext is thread local which means that values stored in the ActionContext are unique per thread
You just create a new Thread so your ThreadLocal variables are not available there. You should do something like this:
import com.opensymphony.xwork2.ActionContext;
if( loginSuccess(userInfo) ) {
ActionContext context = ActionContext.getContext();
initializeDatas(context); // calling thread after userInfo bean validated
// redirecting to home page
return HOME_PAGE;
}
The best way will be pass context to Thread constructor. But I am not sure that COntext is ThreadSafe.
I'm just wondering WHY do you need to start a new Thread to put some data in session
(thing that you say you wanna do, but that you actually don't do in the posted code, where you instead put stuff in request).
You can simply implement SessionAware Interface from your Action(s).
Actions that want access to the user's HTTP session attributes should
implement this interface.
This will give them access to a Map where they can put objects that
can be made available to subsequent requests.
Typical uses may be cached user data such as name, or a shopping cart.
It is not mandatory, but it is a best practice for accessing session from within the Actions, instead of asking to ActionContext:
You can obtain the session attributes by asking the ActionContext or
implementing SessionAware. Implementing SessionAware is preferred.
If needed, here is a little example of usage: http://www.splinter.com.au/how-to-use-sessions-with-struts-2/
if( loginSuccess(userInfo) ) {
// redirecting to home page
return HOME_PAGE;
initializeDatas(); // calling thread after userInfo bean validated
}
That won't work. The method will end after the return call. Try calling the method that creates the new thread first.
if( loginSuccess(userInfo) ) {
// redirecting to home page
initializeDatas(); // calling thread after userInfo bean validated
return HOME_PAGE;
}

getThreadLocalRequest().getSession(false) always null

i have some problems trying code login+cookies .. when the user is login i create the session
getThreadLocalRequest().getSession(true)
and when i want to check if session its still alive always return null
HttpSession session = getThreadLocalRequest().getSession(false);
if (session != null) {
}
When i check the HttpRequest (when i check session alive) this have
Cookie: JSESSIONID=a1042a8e-9ebc-45b8-a3d8-12161885be96
and the cookie is ok.
I use Eclipse+Development mode
Server side code :
public String login(String rut, String pass) throws AuthenticationException {
//if UserPassMatch ...
session = this.getThreadLocalRequest().getSession(true);
//set user bean
session.setAttribute("beanSession", us);
HttpServletResponse response = getThreadLocalResponse();
Cookie usernameCookie = new Cookie("JSESSIONID", us.getSessionID());
usernameCookie.setPath("/");
usernameCookie.setMaxAge(60 * 60 ); //1 hora
response.addCookie(usernameCookie);
}
#Override
public String checkIfSessionStillActive(String token) {
HttpServletRequest request = getThreadLocalRequest();
//Here ALWAYS return null
HttpSession session = request.getSession(false);
if (session != null) {
//check sessionId and search User Bean
}
return token;
}
From client side nothing special just call checkIfSessionStillActive for check if session exists and go throw the token or go to login if it's not. When the user is logged in still return session NULL. I use MVP pattern and i call from AppController and i use the same rpcService. At once the user login i check session and its exists, but if i call checkIfSessionStillActive this not found any session.
Really i read a lot of code and what i found its almost the same thing, ¿can any help me?
Are you using a subclass extending RemoteServiceServlet and calling on a object created somewhere else (for example in spring context) and have extended RemoteServiceServlet? If yes following will solve your problem
For each request a new instance of RemoteServiceServlet is created. Problem is that the thread local variables defined in super class of RemoteServiceServlet are not static, hence for each object you have different variable. When ever you process call in above scenario, your request response thread local variables are initialized for the object which receives but it does not sets thing for object on which you are invoking a method.
I used a workaround by creating a Class with static threadlocal varrible and set values before invoking on second object. Now swcond object can also access them.
Have you tried using setMaxInactiveInterval() rather than messing with the cookie directly?

Categories