How to pass an Object from a Servlet to JSR-356 WebSocket - servlets

I have a JSP-type servlet that registers a WebSocket Endpoint with the Servlet container.
I want to pass a reference of that servlet, and/or some of its objects, to the WebSocket Endpoint, so that I can use the code from that servlet, e.g. for Authentication or Session management (the servlet has its own non-Java EE Session management).
I was hoping that I could set some attribute somewhere when I call addEndpoint() on ServerContainer, because at that point I have access to the objects that I want to use later, but none of the classes that I've seen at that point have an attribute collection, e.g.
objectThatWillBeAvailableAtWebSocket.addAttribute("some.custom.object", someObject);
By the time my code reaches an ServletRequestListener, ServerEndpointConfig.Configurator, or the registered Endpoint, I do not have any reference to the original servlet that added the Endpoint.
How can I pass an Object to the WebSocket servlet? I'm running my test code in Embedded Jetty, but I'm aiming for Container-agnostic code.

Related

Annotation Based Handler Mapping in spring mvc

I want to understand how HandlerMapping work in Annotation based Spring MVC applications. As while working in XML based configuration we have one default and if we want to use other implementation then we have to define it in XML file as well as URL mapping strategies.
To understand HandlerMapping in Annotation based Controller application i came across to
DefaultAnnotationHandlerMapping which used to be default before v3. 1 and now
RequestMappingHandlerMapping is currently used. So I want to understand how to define this HandlerMapping if we are not using XML based configuration and URL mapping strategies. Another thing I came across was HandlerAdapter. So these two things are confusing me.
Please explain step by step when Dispatcher Servlet intercept a request how it find which HandlerMapping to use and how URL mapping strategies work in Annotation based apps.
You can think that HandlerMapping determine a request/URL should be handled by which ways/frameworks (e.g use #Controller to handle ? Use JSP to handle ? etc)
HandlerAdapter drives the actual workflow of handling this request , containing the actual implementation of handling logic.
High Level Logic:
DispatcherServlet intercepts a request
Find out which HandlerMapping can handle this request. Refer to HandlerMapping#getHandler() for the matching logic. It will return a generic object (called a handler object) if the request can be handled.
Find out which HandlerAdapter can handle this handler object (By checking HandlerAdapter#supports()). If a HandlerAdapter can handle , it will handle it (by HandlerAdapter#handle).

What is the complete lifecycle of an OData controller http request in WebApi 2

I wonder what is the full lifecycle of an odata http request over an ODataController hosted in IIS.
For instance:
What are the IIS pipelining steps ?
How is the request handled when entering the ASP.NET controllers area ?
When routing is applied ?
When the Attributes such HttpPost, ApplyFilter are applied ?
Maybe this thread can help you:
The ASP.NET Web API 2 HTTP Message Lifecycle in 43 Easy Steps
It all starts with IIS:
IIS (or OWIN self-hosting) receives a request.
The request is then passed to an instance of HttpServer.
HttpServer is responsible for dispatching HttpRequestMessage objects.
HttpRequestMessage provides strongly-typed access to the request.
If one or more global instances of DelegatingHandler exist on the pipeline, the request is passed to it. The request arrives at the instances of DelegatingHandler in the order said instances were added to the pipeline.
DelegatingHandler instances can skip the remainder of the pipeline and create their own response. I do exactly this in my Custom Validation with FluentValidation post.
If the HttpRequestMessage passes the DelegatingHandler instances (or no such handler exists), then the request proceeds to the HttpRoutingDispatcher instance.
HttpRoutingDispatcher chooses which routing handler to call based on the matching route. If no such route exists (e.g. Route.Handler is null, as seen in the diagram) then the request proceeds directly to Step 10.
If a Route Handler exists for the given route, the HttpRequestMessage is sent to that handler.
It is possible to have instances of DelegatingHandler attached to individual routes. If such handlers exist, the request goes to them (in the order they were added to the pipeline).
An instance of HttpMessageHandler then handles the request. If you provide a custom HttpMessageHandler, said handler can optionally return the request to the "main" path or to a custom end point.
The request is received by an instance of HttpControllerDispatcher, which will route the request to the appropriate route as determined by the request's URL.
The HttpControllerDispatcher selects the appropriate controller to route the request to.
An instance of IHttpControllerSelector selects the appropriate HttpControllerDescriptor for the given HttpMessage.
The IHttpControllerSelector calls an instance of IHttpControllerTypeResolver, which will finally call...
an instance of IAssembliesResolver, which ultimately selects the appropriate controller and returns it to the HttpControllerDispatcher from Step 11.
NOTE: If you implement Dependency Injection, the IAssembliesResolver will be replaced by whatever container you register.
Once the HttpControllerDispatcher has a reference to the appropriate controller, it calls the Create() method on an IHttpControllerActivator...
which creates the actual controller and returns it to the Dispatcher. The dispatcher then sends the request into the Select Controller Action routine, as shown below.
We now have an instance of ApiController which represents the actual controller class the request is routed to. Said instance calls the SelectAction() method on IHttpActionSelector...
Which returns an instance of HttpActionDescriptor representing the action that needs to be called.
Once the pipeline has determined which action to route the request to, it executes any Authentication Filters which are inserted into the pipeline (either globally or local to the invoked action).
These filters allow you to authenticate requests to either individual actions, entire controllers, or globally throughout the application. Any filters which exist are executed in the order they are added to the pipeline (global filters first, then controller-level filters, then action-level filters).
The request then proceeds to the [Authorization Filters] layer, where any Authorization Filters which exist are applied to the request.
Authorization Filters can optionally create their own response and send that back, rather than allowing the request to proceed through the pipeline. These filters are applied in the same manner as Authentication Filters (globally, controller-level, action-level). Note that Authorization Filters can only be used on the Request, not the Response, as it is assumed that if a Response exists, the user had the authorization to generate it.
The request now enters the Model Binding process, which is shown in the next part of the main poster. Each parameter needed by the action can be bound to its value by one of three separate paths. Which path the binding system uses depends on where the value needed exists within the request.
If data needed for an action parameter value exists in the entity body, Web API reads the body of the request; an instance of FormatterParameterBinding will invoke the appropriate formatter classes...
which bind the values to a media type (using MediaTypeFormatter)...
which results in a new complex type.
If data needed for a parameter value exists in the URL or query string, said URL is passed into an instance of IModelBinder, which uses an IValueProvider to map values to a model (see Phil Haack's post about this topic for more info)....
which results in a simple type.
If a custom HttpParameterBinding exists, the system uses that custom binding to build the value...
which results in any kind (simple or complex) of object being mappable (see Mike Stall's wonderful series on this topic).
Now that the request is bound to a model, it is passed through any Action Filters which may exist in the pipeline (either globally or just for the action being invoked).
Once the action filters are passed, the action itself is invoked, and the system waits for a response from it.
If the action produces an exception AND an exception filter exists, the exception filter receives and processes the exception.
If no exception occurred, the action produces an instance of HttpResponseMessage by running the Result Conversion subroutine, shown in the next screenshot.
If the return type is already an HttpResponseMessage, we don't need to do any conversion, so pass the return on through.
If the return type is void, .NET will return an HttpResponseMessage with the status 204 No Content.
If the return type is an IHttpActionResult, call the method ExecuteAsync to create an HttpResponseMessage.
In any Web API method in which you use return Ok(); or return BadRequest(); or something similar, that return statement follows this process, rather than any of the other processes, since the return type of those actions is IHttpActionResult.
For all other types, .NET will create an HttpResponseMessage and place the serialized value of the return in the body of that message.
Once the HttpResponseMessage has been created, return it to the main pipeline.
Pass the newly-created HttpResponseMessage through any AuthenticationFilters which may exist.
The HttpResponseMessage flows through the HttpControllerDispatcher, which at this point probably won't do anything with it.
The Response also flows through the HttpRoutingDispatcher, which again won't do anything with it.
The Response now proceeds through any DelegatingHandlers that are set up to handle it. At this point, the DelegatingHandler objects can really only change the response being sent (e.g. intercept certain responses and change to the appropriate HTTP status).
The final HttpResponseMessage is given to the HttpServer instance.
which returns an Http response to the invoking client
Looking at the source code ,ODataController is another controller which is inherited from
ApiController with custom routing and formatting. So I guess all the logic applied for ApiController
applies to that as well.It also has Custom Formatting and Custom Routing applies using ODataFormatting and ODataRouting
What are the IIS pipelining steps ?
IIS pipelining steps are same like any other mvc controller .In essense,we have all the httpmodules and handlers which forms the pipeline.More details can be found asp.net application lifecycle. From this pieline,when an mvc request comes URLRoutingModule,MvcRouteHandler and Mvchandler works in tandem to serve an MVC request. Explained detailed for the next question.
How is the request handled when entering the ASP.NET controllers area ? When is routing applied ?
Everything starts with an ODataController .Almost everything in MVC is extensible(13 extensibility points in asp.net mvc) you name it and all those points are extended for OData. e.g Starting with Custom Controllers,we have
custom ODataActionSelector which is from IHttpActionSelector .You can find a sample implementation here
IActionValueBinder ,sample implementation here
IContentNegotiator
etc like this many more.
/// Defines a base class for OData controllers that support writing and reading data using the OData formats
/// </summary>
[ODataFormatting]
[ODataRouting]
[ApiExplorerSettings(IgnoreApi = true)]
public abstract class ODataController : ApiController
Receive first request for the application -> In the Global.asax file, Route objects are added to the RouteTable object.
Perform routing -> The UrlRoutingModule module uses the first matching Route object in the RouteTable collection .From ODataRouting, The routes are added to RouteTable collection.
Create MVC request handler -> The MvcRouteHandler object creates an instance of the MvcHandler class and passes the RequestContext instance to the handler
Create controller -> The MvcHandler object uses the RequestContext instance to identify the IControllerFactory object to create the controller instance with
Execute controller -> The MvcHandler instance calls the controller's Execute method
Invoke action -> For controllers that inherit from the ControllerBase class, the ControllerActionInvoker object that is associated with the controller determines which action method of the controller class to call, and then calls that method
7.Action returns all custom CreatedODataResult,UpdatedODataResult etc
There are Custom ODataMediaTypeFormatter registered for ODATA to format the data.

How to access "session" scoped beans in a Spring WebSocket handler (not "websocket" scope)

In a raw Spring WebSocket application (not using sockjs/STOMP or any other middleware), how can I have Spring inject beans that have been registered in the HTTP session scope so that they can be used by code in my WebSocketHandler bean?
Note that what I am not asking is any of these questions:
How do I create beans in a scope that is accessible to all handler invocations for the same WebSocket session (e.g. as described in the answer to Request or Session scope in Spring Websocket). The beans I need to access already exist in the scope for the HTTP session
How do I (programatically) access objects in the servlet container's HTTP session storage (I haven't tried to do this, but I'm pretty sure the answer involves using an HttpSessionHandshakeInterceptor), but that doesn't get me injection of Spring scoped dependencies.
How to use a ScopedProxy to pass beans between code in different scopes (e.g. as described here); I'm already familiar with how to do this, but attempting to do so for a WebSocketHandler causes an error because the session scope hasn't been bound to the thread at the point the object is accessed.
How to access the current security principal -- again, very useful, but not what I'm currently trying to achieve.
What I'm hoping to do is provide a simple framework that allows for the traditional HTTP-request initiated parts of an MVC application to communicate directly with a WebSocket protocol (for sending simple push updates to the client). What I want to be able to do is push data into a session scoped object from the MVC controller and pull it out in the websocket handler. I would like the simplest possible API for this from the MVC controller's perspective, which if it is possible to just use a session-scoped bean for this would be ideal. If you have any other ideas about very simple ways of sharing this data, I'd also like to hear those in case this approach isn't possible.
You can also use Java API for websocket. This link https://spring.io/blog/2013/05/23/spring-framework-4-0-m1-websocket-support
explains how to do this with Spring.
Ufortunately, something like this
#ServerEndpoint(value = "/sample", configurator = SpringConfigurator.class)
public class SampleEndpoint {
private SessionScopedBean sessionScopedBean;
#Autowired
public SampleEndpoint(SessionScopedBean sessionScopedBean) {
this.sessionScopedBean = sessionScopedBean;
}
}
causes exception (because we're trying to access bean outside its scope), but for singleton and prototype beans it works well.
To work with session attributes you can modify the hanshake and pass required attributes:
public class CustomWebSocketConfigurator extends SpringConfigurator {
#Override
public void modifyHandshake(ServerEndpointConfig config,
HandshakeRequest request,
HandshakeResponse response) {
//put attributes from http session to websocket session
HttpSession httpSession = (HttpSession) request.getHttpSession();
config.getUserProperties().put("some_attribute",
httpSession.getAttribute("some_attribute_in_http_session"));
}
}
P. S. More a comment than an answer. I just wanted to add another way of handling session attributes in websocket to your question-answer. I have been searching the web for exactly the same issue and the way showed above seems to me the most systematic approach to handling the session data in websocket.

SessionAware design in Struts 2

I have been working with Struts 2 for a long time.
In case of implementing SessionAware interface to our action class we will get SessionMap but not HttpSession object.
In case of ServletRequestAware and ServletResposeAware we get HttpServletRequest and HttpServletResponse object but not wrapper objects like SessionMap in case of SessionAware.
My question is, if Struts is giving us SessionMap instead of HttpSession to decouple our action classes from Servlet API and Http protocol,then why it is giving us HttpServletRequest and HttpServletResponse objects in case ServletRequestAware and ServletResponseAware.
If Struts doesn't want to decouple Servlet API and HTTP protocol from the action classes then why it is giving us SessionMap in case of SessionAware interface.
Why we don't get HttpSession object?
In case of ServlectRequestAware and ServletResposeAware we get HttpServletRequest and HttpServletRespose object but not wrapper objects like SessionMap in case of SessionAware.
Because those directly expose the servlet request and response on rare occasions where they're actually necessary (or at least useful).
My question is, if struts is giving us SessionMap instead of HttpSession to decouple our action classes from Servlet API and Http protocol,then why it is giving us HttpServletRequest and HttpServletRespose objects in case ServlectRequestAware and ServletResposeAware.
Because it's much less likely you'd specifically need an HttpSession than the actual request or response.
If struts don't want to decouple Servlet API and HTTP protocol from the action classes then why it is giving us SessionMap in case of SessionAware interface.
It does want to decouple the Servlet API, for good reasons. It forces you to explicitly ask for Servlet API artifacts because they're a code smell. It doesn't prevent you from getting them because on rare occasions they're important.
An HttpSession is pretty much just an attribute map, it doesn't contain information generally useful in an action. On the even-rarer occasions you need one you can still get it.
Why we don't get HttpSession object?
You can get this object from the servlet's HTTP request. No reason to define additional interface to inject the HttpSession into the action. On the other hand Struts defines maps for HTTP request, session, application for easier access/modify its attributes using a Map interface. The servletConfig interceptor can inject these objects to the action if it implements corresponding xxxAware interface.
The list of interfaces that could be injected by this interceptor:
ServletContextAware
ServletRequestAware
ServletResponseAware
ParameterAware
RequestAware
SessionAware
ApplicationAware
PrincipalAware

Which context should websocket config go into?

As most people, I have a root and servlet contexts. I need to enable websocket Stomp. I also need to send messages from the Service layer. So how do I configure?
If I put websocket:message-broker into the servlet config, then SimpMessagingTemplate is not autowired in the service layer. If I put it into the root, then it doesn't work at all, it isn't registered as an HTTP handler (even though logs say it does). If I put everything into the dispatcher context, then there is a
java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:252
For now I am going to work around it by calling SimpMessaging from Controller, and not Service, but I'd rather a better solution.

Resources