Is the Java HttpSession ID visible to FreeMarker templates? - java

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.

Related

Can I use Thymeleaf templates + bindings without sticky sessions?

I currently use a HA-Setup without sticky sessions. Is it generally possible to use thymeleaf templates with bound objects in non-sticky-sessions?
I am not familiar with the inner workings of thymeleaf -- neither do I have an idea how to test this...
Thymeleaf would work with the data which you put in your Spring model object. So the scope of that data is that of the request. And moreover, Thymeleaf templates are processed at the server. So the flow is:
User requests for a URL
Spring framework receives it at the server and routes it to the controller
the controller executes the method mapped. This might involve populating the Model or ModelMap object and returns either the view template name or the Model object
the view resolver retrieves the view template name and uses the corresponding view template engine to process the HTML in the view template name and then return the HTML to the response
this response is then sent to the user
So you see there is no sessions involved. But when you use Spring Security, it would use session to record the authenticated user information.
And if the user explicitly uses session in their code then it would be a problem.

How to get a request object in Freemarker

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}

Understanding the flow of spring framework & MVC

I am having some trouble understanding this. Can someone help me better understand this?
MVC
Model --> Java- Spring Framework
View ---> templating language(JSP velocity) & Javascript
DB --> SQL
Q-1)
Now, When I open a particular page, I can't visualize the flow. I've read about DAO, controller , service etc and I understand them individually but I am really confused when I club all together what's the order of execution? Whats the flow exactly ? Is it that first the view is loaded then it sends JS request to fetch the necessary data from backend and then the controller and service are invoked and the DAO queries the db? Then how does the API come into picture? DAO deals with the API?
Q-2)
Why do we need xyz.properties? I have removed a module from my page. If I remove a particular js file(related to that module) from the scripts.properties, then ideally that js should not get executed at all right? Then still why would I see the api call to fetch the data related to that module? I don't see the module but I sure see the api call. Why is that?
DB doesn't enter in MVC model. And you're forgetting a principal element in your analysis: the Controller. The flow goes like this:
Client performs a request to an URL
The application server gets the URL and passes the handling to the web application.
The web application using Spring MVC will handle the URL processing to the Controller: DispatchServlet, which is a Servlet.
The DispatchServlet will try handle the URL. If there's an URL mapping, then it will pass it to the class (mapped in the spring.xml config or decorated with #Controller annotation).
This controller (which in fact is part of the model) will handle the request. It will call services, daos, etc (Model) and return the necessary data to complete the response to the DispatchServlet.
The DispatchServlet will finish the request handling and, in the end, will generate the results e.g. a text/json response, or it will forward to a JSP file (View).
For question two, I never have used such scripts.properties file, so I don't know what you're talking about. Usage of a properties file is to store application properties that should not change until an application redeploy. They have 3 main advantages:
They can be easily manipulated by human users. It's no rocket science to add, edit or remove values.
Since it is a plain text, it's easier to version using a version control system like SVN, Git or another of your preference.
It provides a faster access since it is usually in the same disk as the application, so there's no much time penalty when accessing to its contents compared to a database configuration. But since it is in disk, it still has a disadvantage against RAM access only.
In simple layman's term, MVC explained in pictorial form
(inputing data) (data related part) (display rendering)
-request mapping -classes -JSP (Script,CSS,HTML)
-request param -interface -velocity
Controller ------------->Model--------------->View
||
\/
(data processing logic) (access to Databse)
-optimization -JDBC
-business logic -SQL
Service--------------------->DAO

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.

Best way to show the user full name in a JSP header file with a spring/struts framework?

I have a JSP struts application that uses Spring to integrate with the services/dao/database. Basically, struts uses spring to get the data from the DB, it builds the form and forward them to the JSP files.
I have a header file that is injected in each JSP file using Tiles. I would like to show "Welcome John Doe" on each page inside the header. Where "John Doe" is the name of the currently logged user.
What would be the best approach to do that? The solution that I can think of is:
Use a Spring Filter the catch the http request. Load the user from the database using a cookie that contains the user id(*) and put the name in a session bean named "CurrentUser"
In "header.jsp", get the spring application context. Using it, load the bean "CurrentUser" and get the name. Put the name in the html.
I think I could get this to work. But I'm not certain this is the best way to do it. Any thought on my approach?
(*) Of course, the cookie will be encrypted
Although it may be an extremely large hammer for your fairly simple use-case, we have gotten a really neat spring-jsp integration (jsp 2.1 required!) by using ELResolver. By following this tutorial you can basically inject any spring managed bean into your el-context and allow it to be accessed using jsp-el like this:
${spring.mybean.myproperty}
You can choose to inject pre-defined beans into your el-context or simply pass "mybean" to getBean and allow almost anything spring-managed to be accessible from jsp. mybean could easily be a session-scoped spring bean.
I'm not totally sure how this would align with tiles, though.
Are you not already storing some sort of User object in Session?
If so, I would just add a "getFullName()" method to this domain object and have the DAO populate it when it returns it. Ideally you should populate the User object when the user logs in, store it in session, and not need to load all of the user's details again from the database on each and every page request.
(Are you not using Spring Security? If so, they provide a pretty simple way to store a UserDetails-like object in Session, and easy access to it.)
I'd vote against both of your approaches because
This means (at least) an extra database call per page request
This wouldn't work if other users shared the same bean in the same context. Also, you really shouldn't have JSP files (which are your presentation layer) interacting with data services directly.

Categories

Resources