Showing posts with label Spring Boot. Show all posts
Showing posts with label Spring Boot. Show all posts

Wednesday, October 9, 2019

How to access model attributes inside JavaScript present in Thymeleaf templates?

The prime objective of this write up is to discuss "the how" of accessing model attributes inside JavaScript present in Thymeleaf templates. But I would also be touching on the situation in which I required to access the model attributes inside JavaScript present in Thymeleaf templates which would surely help one to design their web pages in a better manner.

1. Introduction


Thymeleaf offers a series of “scripting” modes for its inlining capabilities so that one can access their exposed Controller's model data inside scripts created in some script languages. Current available scripting modes are javascript (th:inline="javascript") and dart (th:inline="dart").
         I personally believe that it's good to know about the available features in any language like Thymeleaf but it's equally important to know exactly when to use which features? If you are only interested in knowing about Thymeleaf's Script Inlining feature then you could check out section 2 only but if you are also keen to know the instances where I have used this feature while developing a digital learning platform then you should also see section 3.

2. Script Inlining


Below is the sample code snippet which needs to be added in the Thymeleaf page for accessing our exposed Controller's model data inside JavaScripts:
<script th:inline="javascript" type="text/javascript">
/*<![CDATA[*/
    ...

    var username = /*[[${session.user.name}]]*/ 'Anshul';
    var isbn = /*[[${titleModel.isbn}]]*/ 0;
    var assignmentId = /*[[${#httpServletRequest.getParameter('assignmentid')}]]*/ 0;

    $(document).ready(function() {
      
 if ( assignmentId != 0 && assignmentId != null ) {
   ...
 } else {
   ...
 }
    });
/*]]>*/
</script>
where The /*[[...]]*/ syntax, instructs Thymeleaf to evaluate the contained expression.

Few pointers to note here:
  • Thymeleaf will execute the expression and insert the result, but it will also remove all the code in the line after the inline expression itself (the part that is executed when displayed statically). This expression evaluation is intelligent and not limited to Strings. Thymeleaf will correctly convert and write it in corresponding Javascript/Dart syntax. The following kinds of objects conversion are allowed: Strings, Numbers, Booleans, Arrays, Collections, Maps, Beans (objects with getter and setter methods).
  • Being a javascript comment (/*...*/), our expression will be ignored when displaying the page statically in a browser.
  • The code after the inline expression ('Anshul' or  0) will be executed when displaying the page statically.
  • One can also do it without comments with the same effects, but that will make the script to fail when loaded statically. 

3. Requirement & Design Discussion for a module


Recently I have participated in the design & development of a powerful digital learning platform using Microservice architecture. Today we would first know one of the module's requirements at very high level and then discuss different design approaches for developing that. It would give you an idea about when to use Thymeleaf's Script Inlining feature. 

Requirements:

  1. Provide the capability to teachers for managing their created assignments whereas allowing students to view their assigned assignments.
  2. The teacher could click on any assignment from the list of assignments and would see the assignment details page containing details like assignment status, assignment user details, etc in a tab beside the Manage Assignment tab. 
  3. There would be an option(button or Call To Action) in the assignment details tab to preview the questions present in the assignment. 

Design Discussion:


As usual, we too received the requirements gradually i.e. initially we got #1 then much later stage received #2 & #3. Since the layout of both the teacher's Manage Assignments page and student's My Assignments page was almost similar(both shows all the subtopic, multi-subtopic, topic, multi-topic assignments in list views for a title using accordion ) with only one subtle  difference that teacher would see all assignments with some additional details and extra privileges whereas students could see only their assignments. We discussed among us and agreed that we would create a single controller method and single Thymeleaf page for this requirement and would conditionally & dynamically form the page. We implemented this and it worked perfectly fine.

Now at a later stage, we received #2. Now we have to think about its design & implementation approach. Some facts are pretty clear like:
  •  One needs to make a service call to fetch the required assignment, add it in model attributes and dynamically form the Assignment Details tab. 
  • The current Manage Assignment/ My Assignments page data would now appear in a tab and besides that, we would have another tab called Assignment Details. One question pops up, is it a good idea to reload the whole page on click of the assignment and show both Manage Assignment and Assignment Details tab?  You are right Obviously not. So what we had in our hand then, two tabs on the page and same @RequestMapping path in the URL with one additional data i.e. query parameter "assignmentid". So the option for making direct service call was off the chart and it was evident that one needs to make an Ajax call from JavaScript to get assignment details and add the fetched data to the Assignment details tab.

Some more questions regarding the Thymeleaf's capability and implementation appeared like
  • Are Thymeleaf templates smart enough to detect the presence of assignment id in the URL and accordingly make Ajax call to fetch and add respective assignment data in the Assignment Details tab?
  • Do we have all the required parameters like ISBN of a title, "assignmentid" available in the JavaScript to make the service call?  
Now we needed to have the access to our exposed controller's model attributes inside JavaScript to make the service call. We came to know that one can use Thymeleaf's script inlining features to integrate our data inside scripts. 

One thing to note here that after receiving the #2 & #3, we have revisited our implementation for #1 and restructured it. What we did?

We have created a layout HTML page using Thymeleaf which contains
  • HTML article tag having Thymeleaf's th:replace attribute to add the fragments that would form the actual content of the page. This fragment contains multiple empty article tags having a unique id attribute to distinguish between the data for Manage Assignment/My assignments & Assignment Details tab. 
  • Using Thymeleaf's script inlining, we have made the controller's method required parameter available inside JavaScript and then conditionally made the corresponding service calls depending upon the presence of assignment id in the URL and populated the data using jQuery in the respective article tag.
  • One more interesting thing to note here, suppose a user directly wants to view particular assignment details only and not interested in viewing list of assignments then do you think is it a good idea to make two service calls, i.e. one for Manage Assignment/My assignments tab and one for Assignment Details tab? Obviously not right? Therefore we have applied the concept of lazy loading here using JavaScript and by adding a loaded flag. Initially loaded flag would be set to false which means Manage Assignment/My assignments tab is not loaded.  Manage Assignment/My assignments related controller's method would be called only if someone loaded it explicitly, closes the Assignment Details tab, switch to it from any other tabs. 
  • Later we received another requirement where we needed to show some other data in a separate tab on click of some Call to action buttons. Due to the above design approach, it has become very easy. We just added one more blank article tag in the fragment, made the Ajax call and added the data in the newly added article tag using jQuery. 

3. Conclusion


For developers, designers or architects, it's common to think about reusability, redundancy, modularity, readability, scalability while designing any software systems or a web-applications. Thymeleaf provides many features if used carefully could lead to better design of the maintainable, reliable software system. Today we have learned about the Script Inlining feature of Thymleaf and instances where it could be used. I hope it would surely help you while development. Happy Learning !!

Friday, September 20, 2019

Error while creating a project in STS - JSONException: A JSONObject text must begin with '{' at character 0

Recently while trying to create a Spring Boot project in my IDE i.e. Spring Tool Suite(STS, Version:3.9.2.RELEASE) using Spring Starter Project, I have got an error.

Replication Steps: In STS, navigated to File -> New -> Spring Starter Project, and as soon as I clicked on it, I got the error. The errors state that :

JSONException: A JSONObject text must begin with '{' at character 0


 Today I would be sharing the workaround and solution that worked for me. It might help someone who faces a similar issue while creating projects using their IDE.

Workaround & Solution:


Through STS, when anyone tries to create a Spring project then it internally uses Spring Initializr (https://start.spring.io) which is a quickstart generator for Spring projects. It simply means we have a workaround for this problem i.e. generating the project from our browser by accessing https://start.spring.io/, downloading a ZIP of the project, unpacking it locally and at last, importing it using "Import -> Maven -> Existing Maven Project" into STS.

The above workaround should surely work for everyone. It also suggests that our IDE i.e. STS is unable to connect with https://start.spring.io  and this is the root cause of this issue. But how to establish this connection, don't worry just follow the below steps:

Step 1: From STS navigate to Window -> Preferences -> General -> Network Connections
Step 2: In Network Connections, select 'Direct' from Active Provider dropdown and click on 'Apply and Close' button. Choosing Direct causes all the connections to be opened without the use of a proxy server.
Step 3: Now give it a try, create the project using STS i.e. File -> New -> Spring Starter Project.

It should work for you as well.
For reference,


Let me know in the comment section if the workaround and solution have worked for you or not. Happy Learning!!

Monday, June 4, 2018

How to debug errors while using Spring Security module?

If you have ever used Spring Security module for authentication or authorization then you already know the pain while debugging the errors that has encountered while customizing the Spring Web Security i.e. by using annotation like @EnableWebSecurity to customize the Spring Security configuration by extending the WebSecurityConfigurerAdapter base class and overriding individual methods.  Today we would be discussing three ways that would help us to debug Spring Security related error nicely as we will be logging more detailed information in debug mode that would in turn help us in resolving the issues.

Disclaimer: I have tried these methods in Spring Boot and it worked like charm.

1. Turn On the Debug Level log for Spring Framework Web & Security module

As per your convenience, set the below properties in application.yml or application.properties file.
logging.level.org.springframework.security=DEBUG
logging.level.org.springframework.web=DEBUG

2. More concerned about Filter Chain

If one is more concerned about Filter Chain related log information then one could also log in more granular level i.e. logging the FilterChainProxy class.
#application.yml
logging:
  level:
     org:
       springframework:
         security:
          web:
            FilterChainProxy: DEBUG
   
or #application.properties
logging.level.org.springframework.web.FilterChainProxy=Debug   

3. Additional Filter logs specific to a particular request 

If one would like to see what different filters are applied to particular request then one could also set the debug flag to true in @EnableWebSecurity annotation.
@EnableWebSecurity(debug = true)
For reference, see the logs
************************************************************

Request received for GET '/oauth/token':

org.apache.catalina.connector.RequestFacade@2a27c195

servletPath:/oauth/token
pathInfo:null
headers: 
host: localhost:8060
connection: keep-alive
upgrade-insecure-requests: 1
user-agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9
cookie: _ga=GA1.1.46570692.1519211292; JSESSIONID=2BDB6DDBCD404F240AF3DB3331C25BF4


Security filter chain: [
  WebAsyncManagerIntegrationFilter
  SecurityContextPersistenceFilter
  HeaderWriterFilter
  LogoutFilter
  BasicAuthenticationFilter
  RequestCacheAwareFilter
  SecurityContextHolderAwareRequestFilter
  AnonymousAuthenticationFilter
  SessionManagementFilter
  ExceptionTranslationFilter
  FilterSecurityInterceptor
]


************************************************************
One should always keep one thing in mind that depending on the configuration we state in our security configuration class, the order and number of the filters in the filter chain may differ. Let's understand it by an example: http.anonymous().disable() in the class extending WebSecurityConfigurerAdapter class would exclude  AnonymousAuthenticationFilter from the filter chain.

Happy Learning!! Hoping that now you would play with these debug level log and resolve your Spring Security related errors in lesser time. 

Tuesday, May 15, 2018

How to check embedded Tomcat server properties in spring boot?

Hello Friends!! Today we would be discussing how to check the embedded Tomcat server properties in Spring Boot. You must be thinking why would we ever want to check the Tomcat properties because we are the one who has set these properties  using Spring Boot's configuration file i. e.  application.yml / application.properties. But let me first tell you the reason behind it, why I have travelled this extra mile and then we would see how to check the properties?

Q1. Why are we even interested in checking the Spring Boot's embedded Tomcat server properties ?


Recently, I have came across the requirement for setting up the maxSwallowSize property in the embedded Tomcat server of my Spring Boot application which I did it successfully by using Java configuration because as of now while writing this post, this property can't be configured using Spring Boot's configuration file i. e.  application.yml / application.properties.

For configuring maxSwallowSize property,  I have used TomcatConnectorCustomizer interface and then associated it with the TomcatEmbeddedServletContainerFactory class that means manually registered TomcatEmbeddedServletContainerFactory bean in the main Spring Boot class. For more details on this, have a look at this write-up.

Now one question crossed our mind,
Does the manually configured Tomcat server honours the bootstrap. yml file containing some of the configured Tomcat server properties if not then do we have to set all the required properties like maxSwallowSize ?
Logically it should but we can't leave it as granted, we must be sure. That's why we find ourselves in first place to look out a way to check embedded Tomcat server properties.

For reference, bootstrap. yml file,
spring:
  application:
    name: anshuls-blog
      
# EMBEDDED SERVER CONFIGURATION  
server:
  port: 8081
  tomcat:
    max-threads: 1000 # Maximum number of worker threads
    min-spare-threads: 40 # Minimum number of worker threads
    uri-encoding: UTF-8 # Character encoding to use to decode the URI

2. How to check  embedded Tomcat server properties in spring boot?


There are two ways for finding out the configured server properties of a embedded Tomcat server. Both involves, getting the required bean from application context and look out for the desired properties in debug mode.

2.1 Get TomcatEmbeddedServletContainerFactory  bean from Application Context 

Look out the properties inside the TomcatConnectorCustomizer.


2.2 Get ServerProperties bean from Application Context 

ServerProperties.java class contains all the supported embedded servers in Spring Boot as the static inner class i.e. Tomcat, Jetty, Undertow [1]. That's why inspecting it in debug mode shows the Tomcat properties.

For reference, code snippet 
public void getEmbeddedTomcatInfoInSpringBoot() {
  
 TomcatEmbeddedServletContainerFactory tomcatServletContainerFactory = context.getBean(TomcatEmbeddedServletContainerFactory.class);
 Collection<TomcatConnectorCustomizer> tomcatConnectorCustomizers = tomcatServletContainerFactory.getTomcatConnectorCustomizers();
  
 logger.info("URU Encoding:>>>>>>>>>" + tomcatServletContainerFactory.getUriEncoding());
 logger.info("Port:>>>>>>>>>" + tomcatServletContainerFactory.getPort());
  
 ServerProperties serverProperties = context.getBean(ServerProperties.class);
  
 logger.info("MaxThreads Property:>>>>>>>>>" + serverProperties.getTomcat().getMaxThreads());
 logger.info("MinSpareThreads Property:>>>" + serverProperties.getTomcat().getMinSpareThreads());
 logger.info("MinSpareThreads Property:>>>>>" + serverProperties.getTomcat().getUriEncoding());
   
}
Thank you for your time and see you in the next post. Happy Learning!!

Appendix:
[1]: ServerProperties.java

Friday, May 4, 2018

Spring Boot: 'Why' & 'How to' Configure maxSwallowSize property for embedded Tomcat

Hello Friends! Today we would be discussing why in first place, anyone needs to configure maxSwallowSize property and what are the steps that needs to be followed in order to configure this property. Can this property be directly configured by Spring Boot's application.yml / application.properties file or any Java configuration is required for this?



Table Of Content
1. Introduction
2. Why configure maxSwallowSize property
3. How to configure maxSwallowSize property
4. Conclusion

Saturday, March 10, 2018

Create your first Spring Boot web application with Maven & Thymeleaf: 4 Steps(with Screenshots)

Hello Friends!! If you have ever developed the enterprise spring-based applications then you would surely know the pain for making bulky configuration along with the complicated dependency management. Today we would see how Spring Boot takes this pain away. To demonstrate this, we would discuss step by step process to create our first Spring Boot web application using Spring Tool Suite(STS) and then explain how this has become possible using Spring Boot. Don't worry if haven't developed any spring-based application before because this would be very easy to follow guide.
Table Of Content
1. Introduction
2. Scope
3. Tools & Technology Stack Used
4. Steps to create web application
5. Why Spring Boot?
6. Conclusion