Model generation for manually entered page in Spring framework - java

I have to extend some Spring web application, but I'm not very familiar with the framework (however, I have some experience with few other frameworks). I can see that there is "ModelAndView" concept used by the framework. Controller returns both: a model and a view from onSubmit() method. But what to do if a model have to be generated for a page entered manually (user enters the page address to the browser address bar, instead of submitting a form). In such a case there is no onSubmit() call, so a model isn't prepared.
I thought of (ab)using formBackingObject() method of BaseFormController class, which prepares "command" object. But I don't know how to refer the object in the jsp code. Any hints would be appreciated.

You can configure the supported HTTP methods of the controller with the supportedMethods property. The default values are HEAD, GET and POST. If the same parameters are sent with a GET request (there are some restrictions on what can be transmitted) there should be no difference from the controller perspective.
It has to be noted that the HTTP methods have a semantic that should not be broken: get to retrieve (without changes), post to manipulate etc.

The proper method to override to provide model data for the "initial" view is referenceData(). As you can see in the Javadoc, there are two overloads of this method, depending on what you need to do.
Create a reference data map for the given request and command, consisting of bean name/bean instance pairs as expected by ModelAndView.
The default implementation delegates to referenceData(HttpServletRequest). Subclasses can override this to set reference data used in the view.

Related

Swagger API integration for non standard Java technology

We have a system that uses http POST with JSON as an RPC method.
It is an in house solution for internal components communication.
The requests and responses are described each by a Java bean (POJO).
My question is, how can I use swagger annotations to create nice documentation in the swagger standard?
I am not afraid from messing around with existing code, but I was wondering if anyone has some experience with something similar.
The goal is to use Swagger UI to display nice docs and give a playground for users to invoke the Apis.
Based on the comments above, it's impossible to describe this sort of API using Swagger. The Swagger specification is intended to REST-based APIs, where the URLs serve as a unique endpoints to describe an operation, and not the payloads.
By definition, Swagger considers a unique operation to be the combination of a URL and the HTTP method (there are requests to expand the definition to include the mime type as well, for example, but it is not currently available).
There is simply no way to describe a single endpoint that operates multiple requests types, each having its own output.
There may be a solution for what you request in the future, but it is not in the near future, not will it answer your requirements to the fullest.
To be clear - this is not an issue of messing around with code or anything. The specification itself doesn't support it.
There are 2 simple tweaks required to make a swagger file work for any generic hand-built RPC application.
The first tweak is to make the swagger endpoints appear to be unique. This is done by defining each endpoint with a unique name after a hash in the context. This works because your app will not process the url past the '#' and this allows swagger to consider the path to be "unique". In reality though this technique will allow every unique path defined in the swagger file to actually invoke the same endpoint.
paths:
/endpoint#myUniqueCommandA
...
/endpoint#myUniqueCommandB
...
The other tweak is needed to ensure the generated swagger clients will actually call the correct operation inside your RPC app. This is done by implementing a "defaulted single value" enum in each command's request object. The defined enum represents the corresponding attribute / value combo the api needs to pass to get dispatched to the right target action inside your application:
...
definitions:
MyUniqueCommandARequest:
type: object
properties:
rest_call:
type: string
enum:
- myUniqueCommandA
default: myUniqueCommandA
...
MyUniqueCommandBRequest:
type: object
properties:
rest_call:
type: string
enum:
- myUniqueCommandB
default: myUniqueCommandB
...
In the above example, the property "rest_call" is what my underlying system uses to dispatch the request to the right underlying operation.
The request object for myUniqueCommandA has its rest_call attribute defined as enum["myUniqueCommandA"]. The request object for myUniqueCommandB has its rest_call attribute defined as enum["myUniqueCommandB"].
Since these are defined as a single value enums that are also defaulted to that same value, the generated swagger classes that calls these apis will be wired to pass their correct routing value automatically.

Model population in Spring MVC #ExceptionHandler

Is there a way to let my #ExceptionHandler methods have access to the model attributes populated by the #RequestMapping method that triggered the exception in question?
Or, more specifically for my problem: my models passed to my views have some data populated from #ModelAttribute (such as detailed information on the user account) methods, and I'd like those to be also set in my #ExceptionHandler methods.
For instance, since my error view page uses the same header and menu as my other pages, I want to show the current user name (and other info, such as number of unread messages etc).
I know the #ExceptionHandler exists outside the #Transaction (as it should!), so I obviously can't just (and don't want to) run some queries again. Rather, I'd like to pre-populate the ModelMap or ModelAndView or whatever, and make sure the exception handler gets hold of that - or at least that the model data is made available when rendering the view.
I hope this question makes sense, I'm fairly new to Spring MVC so I may be mixing a few concepts here and there...
The javadoc of ExceptionHandler states the following with regard to the arguments that can be passed to the handler method:
Handler methods which are annotated with this annotation are allowed
to have very flexible signatures. They may have arguments of the
following types, in arbitrary order:
1. An exception argument: declared as a general Exception or as a more specific exception. This also serves as a mapping hint if the annotation itself does not narrow the exception types through its value().
2. Request and/or response objects (Servlet API or Portlet API). You may choose any specific request/response type, e.g. ServletRequest / HttpServletRequest or PortletRequest / ActionRequest / RenderRequest. Note that in the Portlet case, an explicitly declared action/render argument is also used for mapping specific request types onto a handler method (in case of no other information given that differentiates between action and render requests).
3. Session object (Servlet API or Portlet API): either HttpSession or PortletSession. An argument of this type will enforce the presence of a corresponding session. As a consequence, such an argument will never be null. Note that session access may not be thread-safe, in particular in a Servlet environment: Consider switching the "synchronizeOnSession" flag to "true" if multiple requests are allowed to access a session concurrently.
4. WebRequest or NativeWebRequest. Allows for generic request parameter access as well as request/session attribute access, without ties to the native Servlet/Portlet API.
5. Locale for the current request locale (determined by the most specific locale resolver available, i.e. the configured LocaleResolver in a Servlet environment and the portal locale in a Portlet environment).
6. InputStream / Reader for access to the request's content. This will be the raw InputStream/Reader as exposed by the Servlet/Portlet API.
7. OutputStream / Writer for generating the response's content. This will be the raw OutputStream/Writer as exposed by the Servlet/Portlet API.
8. Model as an alternative to returning a model map from the handler method. Note that the provided model is not pre-populated with regular model attributes and therefore always empty, as a convenience for preparing the model for an exception-specific view.
So in order to populate the model of the view you will be using to display the error, you'll probably have to go with WebRequest
Thought its possible, but:
http://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc
Important Note: the Model may not be a parameter of any
#ExceptionHandler method. Instead, setup a model inside the method
using a ModelAndView as shown by handleError() above.
Seems you have to cant pass ModelAndView as in any other controller, so it has to be built once again + fetch possible values from HttpServletRequest.

Creating global initBinder using Spring

I am using Spring 3.2 and I am looking for a way that I can force controllers to specify which attributes allowed to be bound, so malicious users can not inject values into bound objects.
Spring recommends using setAllowedFields() to white-list / setDisallowedFields() to black-list.
Instead of doing manually this white-list, I want to do this dinamically, so I want to bound that attributes that are visible on the form.
So is it possible to get this white-list? Is there any way that I can get the visible attributes on the form?
Thanks.
You could implement a RequestDataValueProcessor especially the method processFormFieldValue. You could construct a collection of allowed field names, store this in the session.
Next you would extend the ConfigurableWebBindingInitializer and override the initBinder method. Which would retrieve the collection and pre-configure the WebDataBinder there.
And finally you would need some configuration to wire everything together.
Links
RequestDataValueProcessor javadoc
ConfigurableWebBindingInitializer javadoc

Confusion regarding the behaviour of the request object

I've been messing around with servlets and JSPs and I am a bit confused at something:
I've made a servlet (controller) which would dispatch the request to a JSP
I've set some attributes to the request object using setAttribute() method in my
servlet.
I can access the request object's parameters and attributes within the JSP without any
problem.
Now I've stored the request object as an attribute in the session object using
session.setAttribute("test", request).
I've written a second JSP (navigating to it from the first JSP would be through
Javascript when I click a particular button- by using the window.location function and
giving the address of the second JSP as the value)
In the second JSP, when I retrieve the request object from the session object, I get a
null value from all the attributes of the retrieved request object.
I can access the parameters of the retrieved request object BUT only if I had retrieved
the parameters atleast once in my first JSP using request.getParameter() method
otherwise they return null in my second JSP.
I am really new to this stuff and am confused about this behaviour. Why were my request object's attributes being 'erased' while the parameters remain intact (as long I had accessed the parameters in my first JSP; which is even more bewildering to me as it does not make sense IMO)
Any explanation would be appreciated! Thanking you in advance.
This is just an educated guess, but I think the problem is that request objects in your container of choice might be lazy about its parameters: when you ask it for a parameter it reaches out to some external context and pulls the required data, at the same time caching it.
Nevertheless, the reason of the strange behavior is not really important. The problem should be solved by not saving requests in session. A request object is only your handle to the current request, not a data store by itself. It might be using any mechanism underneath, for all we know the attributes may be stored in threadlocals. There is absolutely no contract that would make a request act as an archive of any sort. For example: what would it mean if I asked such a stored request for the security principal? Would I mean "the current principal of the session"? Would I mean "the principal as of the moment when the request was created"?
EDIT:
Out of pure curiosity I just took a peek at Tomcat's implementation (I have no idea which container you are using) and found that it supports my claims: not only most of the data is gathered lazily, but the request object is recycled! So if you try store it in a session and then use, you might find that you are using someone's else request.
There are 4 scopes in Java EE 5. In both Java EE 6 and Java EE 7 there are 5 scopes. The most used are:
Request scope
Session scope
Application scope (Web Context)
You can store some data in all the above scopes by setting the appropriate attribute.
Here is a quote from the Java EE API docs related to ServletRequest.setAttribute(String, Object) method in regard to request scope:
void setAttribute(java.lang.String name,
java.lang.Object o)
Stores an attribute in this request. Attributes are reset between
requests. This method is most often used in conjunction with
RequestDispatcher.
...
So with every new request the previous attributes you have set in request will be lost. After you have set an attribute in a request, you must forward the request to the desired page. If you redirect, this will be a totally NEW request, thus the attributes previously set will be lost. (If you still want use redirection read this: Servlet Redirection to same page with error message)
Those attributes that are set in a HttpSession (in the session scope) will live as long as the session lives and, of course, will be available to only the user to which session belongs.
As for the context attributes they are meant to be available to the whole web application (application scope) and for ALL users, plus they live as long as the web application lives.
As a conclusion, if you have previously set an attribute in the session it will be available to the same user as long as the session is alive.
Hope this will help you.
P.S.
Maybe this article will also be useful for you: How Java EE 6 Scopes Affect User Interactions
The only thing that this article uses Annotations for scoping, but you'll get the idea.

How to display common information in multiple views in an MVC application?

What is the best way to share common objects between multiple views in an MVC application? Say I have a LoginController that takes a user name and password and authenticates the user and loads their data (account info, full name, etc.). I want to display this on each page - something like a header with "Welcome <user name>, you have <account value> in your account." I don't think I should just store that user object in session. Do I have to return it with each controller?
I'm using the Spring framework for this application, but I don't think that matters. There must be some generic way to handle this common use case.
Update
Not sure if this matters, but I also need the UserID (a primary key returned upon login) as a parameter into other controllers. As this is just another value on the user object returned but not displayed, I would think the answer would be the same as data that is displayed.
You're not really sharing common objects - this is common data (and yes, wrapped by an object). Lets say you have a minimal UserInfo class and a corresponding template fragment that displays it. That fragment will be included in your views.
But regardless of the framework (and how you add this common fragment to your views) the framework/template engine will need to find a 'userInfo' binding and get the required fields.
Unless you are planning on hitting your (db) back-end on every page request to get that information, you will need to cache it. Typically this will be in the session.
If there's quite a lot of logic associated with the common elements, it may be easier to perform a sub-request using ServletRequest.getRequestDispatcher() aka <jsp:include />, then you can go through the whole request processing cycle again with a "Sub-Controller" and "Sub-View".
EDIT: look at Spring MVC HandlerInterceptors
I've handled this exact use case before in a Spring MVC application by having a HandlerInterceptor (Javadoc link) add these details to the ModelAndView for all pages in which I needed it.
Since the whole purpose of a HandlerInterceptor is to be able to have common functionality applied to many requests and/or responses by a single piece of code, this is a natural fit. An Interceptor allows you to hook into either the pre- or post-handle step of a Controller; and you can configure your UrlHandlerMapping to only apply the interceptor to certain URLs (or patterns of URLs) if you wish.

Categories

Resources