How to get a request object in Freemarker - java

In Velocity template engine I could just use a model variable
$request
which is a instance of HttpServletRequest. How to get a http request object in Freemarker template engine? According to the freemarker documentation,
http://freemarker.org/docs/api/freemarker/ext/servlet/HttpRequestHashModel.html#getRequest--
there is a class HttpRequestHashModel and its method returns a instance of HttpServletRequest.
So the question is, how to access this object in spring boot? I found some information about using a
${Request}
variable, but I got an error that it returns a null/missing object.

As far as I know, Spring does not expose the request directly to the template, however by default it does expose the model attribute springMacroRequestContext, which contains a lot of information about the request.
The springMacroRequestContext variable allows you to fetch information about the request.
For instance:
<html lang="${springMacroRequestContext.locale.language}" class="no-js">
or
${springMacroRequestContext.contextPath}
With your requirement of getting the path:
${springMacroRequestContext.requestUri}
should probably be sufficient.
See the org.springframework.web.servlet.support.RequestContext for all the available methods.
You can change the name of this attribute by setting the following property in your application.properties:
spring.freemarker.request-context-attribute=rc
This allows you to shorten the syntax in your template:
${rc.locale}

Related

Are Spring Model objects (and their attributes) tied to their respective controller endpoints / templates?

I'm just starting with spring so please bear with me. I've just solved a bug in my code that was coming from my assumption that once an attribute is added to any Model object, it would also be available to the templating implementation at other endpoints.
#GetMapping("/user_page")
public String getUserPage( Model model ) {
Page page = new Page();
model.addAttribute("user_page", page);
return "user_page";
In my Thymeleaf template I was able to use this attribute fine at user_page.html. Now at another endpoint and template I was also trying to use this user_page attribute. Note that it was throwing some errors:
Exception evaluating SpringEL expression:
and
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'name' cannot be found on null
It looks like Thymeleaf couldn't find the user_page attribute.
but I also hadn't added a Model parameter to the controller that handled this other endpoint. After adding a Model to the method parameters and adding the page again model.addAttribute("user_page", page);, this time to the controller handling the different endpoint, the problem went away.
Is Spring autowiring non-singleton Model objects to these controllers? Why did I have to add the same page instance to the model twice? So are these Models tied specifically to the template (maybe even endpoint) that their respective controller returns?
Read Dispatcher Servlet Processing Sequence.
Are Spring Model objects (and their attributes) tied to their respective controller endpoints / templates?
There is no such a thing, as "Model's respective controller"; rather, a fresh instance of the Model's implementation gets instantiated each time, any handler method gets invoked.
When an HTTP request hits dispatcher servlet, and the latter passes the servlet request-response objects into the corresponding handler method, Spring MVC's infrastructure looks up the signature of corresponding handler method and passes a fresh instance of the Model (along with many others), if it is expected.
You can also use modelAttribute element in your template's form, and this way, you will directly bind the data to the handler method's Model parameter, having the argument being pre-filled with the form data. In this case, you can also enable Bean Validation.

Is there a Spring annotation to simplify throwing an error if the id field is in the request body

From what I have read about REST:
The id of a resource should be a path variable, rather than in the request body
If there is an id in the request body, it is invalid input and should return 400
Does Spring Annotations provide a simple way to add this check to what is validated with #Valid?
I can certainly code this myself. I just want to use as many Spring Annotation shortcuts as are available. I am looking for some kind of annotation that I can put on the Model (or elsewhere, I guess) that throws an error if a field is present in the #RequestBody object, but does not prevent a model from being persisted with a value in that field.

Passing variables from JSP to servlet

All the time, when I searched on Google, I got dozen of answers which are posted in Stackoverflow about passing variables to servlet from JSP.
But I am wondering, I don't get answer of: How to pass a variable from JSP to a servlet class? Is it possible?
Actually I am doing a simple PhoneBook application. Here I have to send contact id to a servlet for editing and deleting. How can I pass this value?
I know, we can pass variable from servlet to JSP by using request.setAttribute(key, value)
But when I used it to set variable in JSP and again get it by using session.getAttribute(key ) then result is null.
God help me.
The standard way of passing/submitting data to the server in the pure Servlets/JSP world (as in your case from the JSP to the servlet) is by using HTML form, i.e. the same way as when using other technologies (ASP.NET, PHP etc). And it doesn't matter whether it is a pure HTML page or JSP page. The recommended/most used method of submitting data from the form to the server is POST.
You also can pass data in the query string that is contained in the request URL after the path (this also happens when instead of POST you use GET method in the form). But that is for the simple cases, like constructing URLs for the pagination etc (you can see the example of constructing URLs with the additional queries here: Composing URL in JSP)
Example of passing parameters in the URL:
http://example.com/foo?param1=bar&page=100
For the difference between submitting data using GET and POST methods read here:
GET versus POST Requests on HTML
Forms
In HTML forms, what’s the difference between using the GET method
versus
POST?
So you can configure some servlet to process data sent/submitted from a JSP or HTML etc.
It is highly recommended to submit data using POST method and respectively to process the submitted data using the doPost() method in your servlet.
You will then get the parameters passed by the client in the request by using one of the following ServletRequest methods:
java.lang.String getParameter(java.lang.String
name)
java.util.Map
getParameterMap()
java.util.Enumeration
getParameterNames()
java.lang.String[] getParameterValues(java.lang.String
name)
Here is a nice tutorial with examples: Handling the Client Request: Form Data
The above tutorial is from the following course:
Building Web Apps in Java:
Beginning & Intermediate Servlet & JSP Tutorials
Another way of exchanging data using Java EE is by storing data as attributes in different scopes. (Following is the excerpt from one of my answers on SO)
There are 4 scopes in Java EE 5 (see The Java EE 5 Tutorial: Using Scope Objects). In Java EE 6 and in Java EE 7 there are 5 scopes (see The Java EE 6 Tutorial: Using Scopes and The Java EE 7 Tutorial: Using 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.
Also maybe this article will be useful for you as well: How Java EE 6 Scopes Affect User Interactions
Also pay attention to the following issue. You wrote (quote):
I know , We can pass variable from servlet to jsp by using request.setAttribute(key , value)
But when I used it to set variable in jsp and again get it by using session.getAttribute(key ) then result is null.
As the users #neel and #Sanchit have noticed, you are setting an attribute in the request object, but trying to get it back from the session. No wonder you are getting null in this case.
Hope this will help you.

What is a "request scoped variable" in JSF

I was reading an article titled: "JSF 2 GETs Bookmarkable URLs".
The article has the following paragraph:
Introducing view parameters
The API documentation describes a view parameter, represented by the javax.faces.component.UIViewParameter component class, as a declarative binding between a request parameter and a model property. The binding to the model property is expressed using an EL value expression (e.g., #{blog.entryId}). If the expression is omitted, the request parameter is bound instead to a request-scoped variable with the same name.
Could someone kindly provide an example of a request scoped variable.
A "request scoped variable" is an variable which is stored as an attribute of the HttpServletRequest.
request.setAttribute("foo", foo);
This attribute is available in EL the usual way by #{foo}. The HttpServletRequest itself has a lifetime of exactly one HTTP request-response cycle. Once the HTTP response associated with the HTTP request has arrived fully at the client (the webbrowser), then the HttpServletRequest instance, including all of its attributes, is garbaged. JSF request scoped managed beans are by the way also stored as an attribute of the HttpServletRequest.
As JSF runs "on top" of the basic HTTP Servlet API, this is all easier to understand if you also understand how HTTP and the Servlet API work. This answer might give some enlightenment: How do servlets work? Instantiation, sessions, shared variables and multithreading.
Your subsequent question shall probably be "How is this related to the quoted paragraph then?" Well, it is basically telling that, when you omit the value attribute of the <f:viewParam>, that it instead is been put as a variable in the request scope.
So, if you use
<f:viewParam name="entryId" />
instead of
<f:viewParam name="entryId" value="#{blog.entryId}" />
then it becomes available as #{entryId} in the request scope.
<p>The entry ID view parameter is: #{entryId}</p>
This is however not the way view parameters are usually been used. You'd alternatively also just have used the #{param} map instead, hereby making the whole <f:viewParam> superfluous.
<p>The entry ID view parameter is: #{param.entryId}</p>
See also:
ViewParam vs #ManagedProperty(value = "#{param.id}")
A request scoped variable is instancinated for a each single request. So a request scoped variable instance does not exist in the context of another request.
A request scoped variable is, as the name implies, only valid in the current http request. A good use for request variables is when forwarding a request from a servlet to jsp. E.g set the variable in servlet, later read the same variable in jsp with ${myvar}
example(servlet)
request.setAttribute ("greeting", "world");
getServletConfig().getServletContext().getRequestDispatcher("/jsp/page.jsp").forward(request, response);
example(jsp)
Hello ${greeting}
id is mapped with entryId in Managed-bean config or u can use annotations.
<managed-bean>
<managed-bean-name>blog</managed-bean-name>
<managed-bean-class>com.acme.Blog</managed-bean-class>
<managed-property>
<property-name>entryId</property-name>
<value>#{param['id']}</value>
</managed-property>
</managed-bean>
#RequestScope: (this is the default scope of a managed bean). This puts the bean in request scope. It makes a new instance for every HTTP request. Commonly, the bean is instantiated twice, once when form is displayed and once when it is submitted.

Is the Java HttpSession ID visible to FreeMarker templates?

From a FreeMarker template in a Java EE web application, I need to access the sessionID (i.e. HttpSession.getId()). Long story short, it's being passed to an outside analytics provider so they can build reports about what users do during their browsing session.
Obviously, I just add the session ID to the model object which gets passed to FreeMarker. However, this application is a bit of a mess... one FreeMarker template may be used by multiple controllers passing various model objects. For maintainability, it would be far easier if I could just access the session ID from the FreeMaker template without having to change all those model classes.
I've found FreeMarker documentation referencing "application", "session", and "request" scope. However, this format does not return a value:
${Session.id}
I suspect "scope attributes" doesn't include all getter methods on the HttpSession object (such as getId())... but rather just those values which can be fetched from HttpSession.getAttribute().
Is there an easy way to access the Java EE session ID from a FreeMarker template, without having to explicitly pass it through the model object?
You can put it in the model before rendering the template.
Normally you can put the request object in the model in some base method, which is invoked when rendering all templates. That way all templates will have the request, which you need anyway. Then you access the session via the request object. That's what we've done, and it works fine.

Categories

Resources