Can I use WebServiceContext and the method getMessageContext() in a web service to get a HttpSession object for save and get a session value? I was trying use the HttpSession in a web service like this:
#WebService
#SOAPBinding(style = SOAPBinding.Style.RPC, use = SOAPBinding.Use.LITERAL, parameterStyle = SOAPBinding.ParameterStyle.WRAPPED)
public class DummyWs {
#Resource
private WebServiceContext wsContext;
#WebMethod(operationName = "sayHello")
public String sayHello(#WebParam(name = "name") String name) {
return "hello " + name;
}
#WebMethod(operationName="setValue")
public void setValue(#WebParam(name = "value") String newValue) {
MessageContext mc = wsContext.getMessageContext();
HttpSession session = ((javax.servlet.http.HttpServletRequest)mc.get(MessageContext.SERVLET_REQUEST)).getSession();
session.setAttribute("value", newValue);
}
#WebMethod(operationName="getValue")
public String getValue() {
MessageContext mc = wsContext.getMessageContext();
HttpSession session = ((javax.servlet.http.HttpServletRequest)mc.get(MessageContext.SERVLET_REQUEST)).getSession();
return (String)session.getValue("value");
}
}
I saw other examples that uses the #Stateful annotation, but I don't use this. Is necessary use the #Stateful annotation? What happened if I don't use this annotation?
Did you see the sample stateful included in the Reference Implementation zip distribution?
The sample use the annotation com.sun.xml.ws.developer.Stateful in the web service implementation and the class com.sun.xml.ws.developer.StatefulWebServiceManager for store the objects. As Java Web services are required to be stateless, we need to
save the contents of the objects in a persistent storage across client calls.
In another way, you should prefer a staless service. The failure-handling, the interaction with transactional semantics is simple. And the reusability is enhanced.
Related
I need to validate HttpSession (for Spring MVC Application) in a better way for my current Project.
Here is the Scenario:
1) Once user is successfully validated, userObject object is added to httpSession class
HttpSession session = req.getSession(true);
session.setAttribute(AppConstants.LOGGEDIN_PARAM, userDetail);
2) Then for each request, userObject is retrieved from HttpSession Class to validate user Session
#RequestMapping(value = "/apply", method = RequestMethod.GET)
public String getTourApplyPage(HttpServletRequest req, ModelMap map) {
UserDetailTO userDetail = (UserDetailTO) req.getSession().getAttribute(AppConstants.LOGGEDIN_PARAM);
Long employeeId = userDetail.getUserType() == 1 ? userDetail.getEmployeeId():userDetail.getUserId();
if (employeeId == 0) {
req.setAttribute(AppConstants.MSG_PARAM, "Invalid employee Id.");
return userDetail.getUserType() == 1 ? AppConstants.PIS_MESSAGE : AppConstants.ADMIN_PIS_MESSAGE;
}
...
}
There can be better approaches to set userDetail object inside HttpSession but I had a restriction to not change this implementation (Point 1).
Can it possible to change getting a better implementation for getting a userDetail object from HttpSession (Point 2)?
Is it possible to write a better implementation for getting a userDetail object from httpSession?
Working at such a high level of abstraction, as controllers are at, you don't necessarily need to inject neither an HttpServletRequest nor an HttpSession.
You can make your controller session-scoped and inject a session-scoped bean there. The bean can hold a userDetails and a message for failed validations.
#RestController
#Scope("session")
public class Controller {
#Autowired
private SessionDetails details;
#PostMapping(path = "/validate")
public void validate() {
details.setUserDetails(...);
}
#GetMapping(path = "/apply")
public String apply() {
final UserDetailTO userDetails = details.getUserDetails();
...
}
}
#Component
#Scope("session")
class SessionDetails {
private String message;
private UserDetailTO userDetails;
// getters & setters
}
I use Spring Security, and I found strange behavior of framework while login. Spring Security WebAuthenticationDetails has parameter sessionId which is getting from HTTP request, and it all should be good, but in fact REST request gives me another session id. If I will autowire HttpSession and then get session id from it, I will get Spring-like id. So it seems that I have two ids for one user. Is it correct? Or I missed something?
EDITED:
For example this class will gave some session id
public class AuthenticationEventListener implements ApplicationListener<AbstractAuthenticationEvent> {
#Autowired
HttpSession httpSession;
#Override
public void onApplicationEvent(AbstractAuthenticationEvent event) {
if (event instanceof AuthenticationSuccessEvent) {
LoggedUser loggedUser = (LoggedUser) event.getAuthentication().getPrincipal();
loggedUser.initSessionParams(event.getAuthentication());
String sessionId = httpSession.getId();
}
}
}
and this method will give another one:
#RequestMapping(value = "/chart")
public Map getTestStatusesChart(HttpServletRequest request) {
String sessionId= request.getSession(false).getId();
return null;
}
So the answer is next: with condition of security Spring change session id by default. To prevent such behavior you need to disable session-fixation-protection in Spring Security config. more info by link
I have used below codes for fetching session attributes from session util class(contains static methods). Want to know that below code could be right approach in multithreaded environment or is there any better other ways for fetching sessions from util.
public static HttpSession getSession(){
ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
HttpSession session = attr.getRequest().getSession();
return session;
}
public static String getEmailIDFromSession(){
return (String)getSession().getAttribute("USER_EMAIL");
}
No, it's OK. And it is really thread safe. But from other side you should understand that it will be available only within HTTP Request Thread and from Spring MVC environment.
From other side, if you want to get that attribute from your #Controller or #Service you always can inject session there:
#Controller
class MyController {
#Autowired
private HttpSession session;
}
I'm trying to figure out the best way to handle httpsession in combination with pure EJB web services. I have created a utility class and I have a controller class. Where is the best place to instantiate a utility class inside the controller class? The plan is that each user that visits/calls a webservice i.e. using the website the first time should have a httpsession object assigned to them:
public class Utility {
#Resource
private WebServiceContext wsContext;
public MessageContext mc = wsContext.getMessageContext();
public HttpSession getSession(){
return ((HttpServletRequest)mc.get(MessageContext.SERVLET_CONTEXT)).getSession(true);
}
}
#Path("controller")
#Stateless
public class ControllerEJB {
#POST
public void registerUser(
#QueryParam("fornamn") String fornamn,
#QueryParam("efternamn") String efternamn,
#QueryParam("epost") String epost,
#QueryParam("epost2") String epost2,
#QueryParam("password") String password
){
User user = new User();
user.setEmail(epost);
user.setPassword(password);
user.setFornamn(fornamn);
user.setEfternamn(efternamn);
}
#GET
#Produces(MediaType.APPLICATION_JSON)
public String firstMethod(){
User user = new User();
user.setEmail("sam.gholizadeh");
return "unfisnihedmethod";
}
}
I've followed this tutorial http://docs.oracle.com/cd/E12839_01/web.1111/e13734/stateful.htm but as metioned earlier I'm not sure how and where to implement the logic that keeps track if a visitor has been assigned a session id or not.
Edit: Should the controller class be stateful or stateless?
Since you are using JAX-RS, it's even easier to directly get the HttpServletRequest using JAX-RS:
#Path("controller")
#Stateless
public class ControllerEJB {
#POST
public void registerUser(
#QueryParam("fornamn") String fornamn,
#QueryParam("efternamn") String efternamn,
#QueryParam("epost") String epost,
#QueryParam("epost2") String epost2,
#QueryParam("password") String password,
#Context HttpServletRequest request){
HttpSession session = request.getSession(true);
...
}
}
I have a simple web service like this:
#WebService
public class MyWebService
{
#WebMethod
public String ProcessQuery(#WebParam(name="query") String q)
{
// Logging here: User IP, etc.
}
public static void main(String[] args) throws Exception
{
String address = "http://127.0.0.1:8023/_WebServiceDemo";
Endpoint.publish(address, new MyWebService());
new DocumentServer();
System.out.println("Listening: " + address);
}
}
I want to add a logging method for my service to extract information. I've heard about NCSA format and Log4J but I don't know how to use them in the service. I want to log user's ip and other info. How can I do it?
Thanks.
Edit: I should note that the main part of my question is how can I retrieve some data such as user's IP, client, etc. in the web method.
Add WebServiceContext to your class, so you can get the HttpServletRequest:
#WebService
public class MyWebService
{
#Resource
WebServiceContext wsContext;
#WebMethod
public String ProcessQuery(#WebParam(name="query") String q)
{
MessageContext messageContext = wsContext.getMessageContext();
HttpServletRequest request = (HttpServletRequest) messageContext.get(SOAPMessageContext.SERVLET_REQUEST);
// now you can get anything you want from the request
}
}