Showing posts with label How To. Show all posts
Showing posts with label How To. Show all posts

Friday, July 10, 2020

JSON Web Token (JWT) Use Case: Secure Information Exchange Between Two Parties

Today our topic of discussion is related to JSON Web Token (JWT). There are mainly two use cases where one can use JWT:
  1. For authentication purposes 
  2. For secure information exchange between two parties 
Out of these two use cases, we would be discussing the second use case today. Although it's not the most usable or most common scenario for using JWT, it offer's a great way for interaction between 3rd party applications/clients and the target application where the target application doesn't want to persist any user-related data corresponding to 3rd party clients in their end. If you are thinking, how come then target application would identify or authenticate the 3rd party clients then you are on the right track, we would be touching this in a while. Please stay with me for a little longer. Apart from this, We would also provide some practical industry standard use-cases of JWT and explain a generic JWT flow using sequence diagram.

1. The Job


Let's discuss the problem statement first.
A third-party application would like to interact with the target application either for
- accessing some protected resource of the target application
- executing some business logic in the target application
For performing these operations, the third-party application must be authenticated & authorized first. Now we will see the traditional way & JWT way as the solution of this problem statement.

2. The Traditional Way 


In the traditional client-server model, the client requests an access-restricted resource (protected resource) on the server by authenticating with the server using the resource owner's credentials.  In order to provide third-party applications access to restricted resources, the resource owner shares its credentials with the third party i.e. the target application's owner create a user in their system for the third-party application. But this creates several problems like:
  • Session Management
  • Performance: Need to make multiple databases calls for authentication every time we log out or our session expires. Also, increase network round-trip time. 
  • Compromise of any third-party application results in compromise of the end user's password and all of the data protected by that password.
The burning question is "How can we avoid these problems then"?  The answer is by using a token-based authentication system. JWT allows the server to verify the information contained in the JWT without necessarily storing state on the server.

3. The JWT Way 


We would be giving a glimpse of use case 1 i.e. using JWT for improving the authentication process and then move on to use case 2 i.e. using JWT for transmitting information securely between the service provider and the client so that we all have a clear understanding about the use cases of JWT.

3.1 For authentication purposes 

After the initial successful authentication (either by using username and password or by other means if using OAuth), the authorization server would generate the JWT and pass it to the client. Now client would use this token in every request while accessing protected resources until the token expires.
It means one will need to authenticate only in two cases:
  • first time to get the token and
  • when token expires
The service provider only cares about the token and it's validity. If the received token is valid then access is granted to the client.

3.2 For secure information exchange between two parties 

Now when we say secure exchange information could happen between two parties then it's important to understand the reason behind it. It raises a very crucial question.
Q1: Is it really a secure and trusted way for information exchange?
The answer would be Yes. One could use JWT for secure information exchange because one could verify the validity of JWT
  • whether the JWT is well-formed or not 
  • whether the signature is matched or not 
  • whether the standard claims in the JWT are as per the agreement or not
Accessibility of secured resources or information exchange between two parties is allowed only if it has passed the validity checks of JWT. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.

4. Real World Use Case 


Let's talk about the real world use case of JWT.

Usecase 1: There is requirement that some of the RESTful services that are being developed by the enterprise would be used by 3rd parties, that means they have to be available outside of the enterprise network. Now the enterprise need to protect such services against unauthorized access and JWT is a good candidate for this scenario.

Usecase 2: Securing the APIs to makes system less vulnerable to any unauthorized access of our data and any kind of attack on the system.

Usecase 3: A partner 3rd party enterprise would like to securely exchange information like It would like to create accounts for their user, would like to fire fulfillment service or would like to access any protected resources. In this case, 3rd party enterprise could be granted JWT by the target enterprise by using Client Credential grant type workflow. Now the 3rd party app could send the JWT, typically in the Authorization header using the Bearer schema and then make a required service calls.

5. JWT Flow: Sequence Diagram


To make everything clear, here the sequence diagram for the JWT workflow which is self explanatory. Here,
- Client is the 3rd part App,
- Application is the Target Application
- Admin is the internal app of the Target Application


6. Conclusion


JWT provides the stateless authentication mechanism as the user state is never saved in the server memory. The server's protected routes will check for a valid JWT in the Authorization header, and if there is, the user will be allowed as JWTs are self-contained, all the necessary information is there, reducing the need of going back and forward to the database.Also one could easily fully rely on data APIs that are stateless for information exchange.

Hoping that this articles would help you understand different usecases where JWT could be used and in what kind of usecases enterprises are using JWT. Happy Learning!!:-)

Wednesday, October 16, 2019

Axios In Action

We all know that Axios is a promise-based HTTP client for the browser and node.js. Although I have used Axios extensively while making GET, POST request calls and multiple concurrent requests call from the front end, I have never used Axios in conjunction with node.js. Today we would be discussing how to use Axios for making any kind of calls from the front end and some other Axios related important stuff.

1. Introduction


Similar to traditional AJAX call, one could easily make Axios calls without much hustle from the front end. One needs to include below JS library in order to work it properly:
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
Today we would be touching on below items:
  • How to make Axios GET / POST calls?
  • How to make multiple concurrent requests calls?
  • How to handle the dependent request calls using Axios?
  • Understanding the response to a request
  • How to handle errors that occurred while making Axios calls?

2. GET Request


Performing a GET request:
// Make a request for a user with a given ID
axios.get('/getAssignment?id=12345')
  .then(function (response) { // handle success
    console.log(response);
  })
  .catch(function (error) {  // handle error
    console.log(error);
  })
  .finally(function () {  // always executed
   ...
  });
Optionally the above request could also be done as
axios.get('/getAssignment', {
    params: {
      id: 12345
    }
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  })
  .then(function () {
    // always executed
  });  

3. POST Request


Performing a POST request:
axios.post('/saveAssignment', {
   'assignmentData' : assignmentData // an array containing: label,type,availableon,dueon etc
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });
Obviously, @RequestMapping i.e. /saveAssignment would call one of our Controller's methods. Worried about how this data would be available in Controller layers? Don't worry? We got you covered here. Just look at the below code snippet:
@RequestMapping(value = "/saveAssignment", headers = "Content-Type=application/json", method = RequestMethod.POST)
@PreAuthorize("isAuthenticated()")
public ResponseEntity<String> saveAssignment(Model model, @RequestBody Map<String, String[]> assignmentDataMap) {

 String[] assignmentData = assignmentDataMap.get("assignmentData");
 ...
} 

4. Multiple concurrent requests


Performing multiple concurrent requests:
function findAssignmentById(assignmentId) {
 return axios.get("/getAssignment?id=" + assignmentId);
}

function findAllAssignmentUser(assignmentId) {
 return axios.get("/getAssignmentUsers?assignmentid=" + assignmentId);
}

axios.all([findAssignmentById(), findAllAssignmentUser()])
  .then(axios.spread(function (assignmentData, userData) {
    // Both requests are now complete
 var assignment = assignmentData.data;
 var users = userData.data;
  }));
Tips: Never use this, when the requests are dependent anyhow.

5. Multiple requests but dependent somehow


It may happen that depending upon the return value from one Axios call, one may require to make another Axios call conditionally. In those cases, one could follow the below approach.
var assignmentId1 = 1234;
axios.get("/getAssignmentUser?id="+assignmentId1).then(function(response) {    
 var assignmentUserFlag = response.data.size() > 0;
 if(assignmentUserFlag){
  axios.get("/getAssignment?id="+assignmentId1).then(function(response) { 
  
  }).catch(function (error) {
   ...
  });
 } else {
   ....
 }
}).catch(function (error) {
 ...
});

6. Understanding the response to a request 


The response to a request contains the following information:
{
  // `data` is the response that was provided by the server
  data: {},
 
  // `status` is the HTTP status code from the server response
  status: 200,
 
  // `statusText` is the HTTP status message from the server response
  statusText: 'OK',
 
  // `headers` the headers that the server responded with
  // All header names are lower cased
  headers: {},
 
  // `config` is the config that was provided to `axios` for the request
  config: {},
 
  // `request` is the request that generated this response
  // It is the last ClientRequest instance in node.js (in redirects)
  // and an XMLHttpRequest instance the browser
  request: {}
}
When using then, one will receive the response as follows:
axios.get('/getAssignment?id=12345')
  .then(function (response) {
    console.log(response.data);
    console.log(response.status);
    console.log(response.statusText);
    console.log(response.headers);
    console.log(response.config);
 });

7. Handling Errors


You must be thinking about why there is a separate section for this. From the start of this article, we have maintained that inside catch block i.e. ".catch(function (error) { ..}" we would handle the error, End of the Story right? But wait there is still more left to it. 
axios.get('/getAssignment?id=12345')
  .catch(function (error) {
    if (error.response) {
      // The request was made and the server responded with a status code
      // that falls out of the range of 2xx
      console.log(error.response.data);
      console.log(error.response.status);
      console.log(error.response.headers);
    } else if (error.request) {
      // The request was made but no response was received
      // `error.request` is an instance of XMLHttpRequest in the browser and an instance of
      // http.ClientRequest in node.js
      console.log(error.request);
    } else {
      // Something happened in setting up the request that triggered an Error
      console.log('Error', error.message);
    }
    console.log(error.config);
  });
Point to ponder: Before starting I would like to highlight that the above code snippet is taken from the official website. It's regarding "else if (error.request) {..}" block. It states that "The request was made but no response was received" obviously from the server. Now one open question to you - In Microservice Architecture, suppose service A is calling service B which is down (we have manually stopped it) then no doubt it would enter in catch block but where would the control go, if, else if or last else block? 
According to me, it should go inside else if block as the server is down(service B) but we have made the request properly. But to my surprise, it entered inside if block. But how can that happen when the server was down? How the server can respond? Just for information, in JS, we are getting Internal Server Error(500 status code) whereas in STS console, 404. If you have the answer to the above question or any logical explanation then please share in the comment section.

8. Conclusion


I hope that now you know how to use Axios. It would surely help you while doing development work using Axios. Happy Learning !! ☺

Friday, October 11, 2019

Download data in CSV format using JavaScript

Today we would be discussing Export to CSV functionality using JavaScript. You might be wondering that there are many 3rd party libraries to generate the CSV file using JavaScript/jQuery then why am I reinventing the wheel? Why don't use the already existing solution? Bear with me, I would not only explain why but also describe how to download data in CSV format using JavaScript?

1. Introduction 


It's the very common use-case that we already have some data on the browser (HTML pages) and we would like to provide the option to users to download these data in CSV format using jQuery / JavaScript. That's why there are many 3rd party libraries in the market to generate the CSV file using jQuery but from the HTML table as the source. Just lookout for a solution that facilitates us to generate the CSV file using jQuery / JavaScript if the current HTML structure representing the data on the page is not in the tabular format. This is where our solution comes in the picture which is very simple and handy. One might argue that it is possible to create a temporary table from the complicated HTML structure on the fly in order to use the 3rd party libraries. But again it depends upon the complexity and we won't be discussing that here. 

2. Browser Compatability 


Tested this utility in below version of the browser and it's working as expected:
  • Google Chrome Version 77.0.3865.90 (64-bit)
  • Firefox Quantum Version 69.0(64-bit)
  • IE 11 Version 11.0.9600.19467

3. Why & Implementation


Now again we would reiterate one which situation and why one should use this Export to CSV utility developed using JavaScript and then directly jump on the implementation.

3.1 Why? 

  • Preferred to use if the current HTML structure is not in tabular format and very complicated  but one could use it even if HTML structure is in tabular format 
  • Handling boundary usecases: Currently if data values have comma then also it properly handles it. 
  • Simple to use
  • Don't have to load any 3rd part library 

3.2 Implementation 


One needs to just create the multi-dimensional data array from the HTML page containing the data using jQuery / JavaScript and then we are good to go. Here for the demo purpose, we have created the multi-dimensional data array manually inside JavaScript. 
<html>
<head>
<title>Download CSV</title>
<script>
// prepare the data from the HTML page using jQuery/JavaScript.
// Demo purpose, we are manually preparing the data
var data = [
   ['Anshul', 'programmer','Gamer'],
   ['Rahul', 'Computer Science Engineer','Traveller'],
   ['Rajnikant', 'Hero','Sky Ga,zing']
];


function downloadCSV() {
    var csv = 'Name,Job,Passion\n';
 
 data.forEach(function(row) {
        var row1 = []; 
        row.forEach(function(item) { // handling commna in data values
        if(item.indexOf(',') == -1) { // not having comma 
    row1.push(item);
  } else {
    item = "\"" + item + "\"";
    row1.push(item);
  }
     });
 console.log("row1:" + row1)
 csv += row1.join(',');
 csv += "\n";
     });
 
 if (navigator.msSaveBlob) { //IE
  var csvURL =  null;
  var csvData = new Blob([csv], {type: 'text/csv;charset=utf-8;'});
                csvURL = navigator.msSaveBlob(csvData, 'download-reports.csv');
 } else { // Firefox,Chrome
         console.log(csv);
  //var hiddenElement = document.createElement('a');
                var hiddenElement = document.getElementById('dummyDownload'); //For Firefox 
  hiddenElement.href = 'data:text/csv;charset=utf-8,' + encodeURI(csv);
  hiddenElement.target = '_blank';
  hiddenElement.download = 'download-reports.csv';
  hiddenElement.click();
    }  
}
</script>
</head>
<body>
<a id=dummyDownload hidden></a> 
<button onclick="downloadCSV()">Download CSV</button> 
</body>
</html>

4. Downloaded CSV File


For reference, showing the downloaded CSV file in both the notepad++ & by Open Office(Separated by option: Comma). See the last row in which, intentionally I have put a comma in one of the data values but our utility properly handles it. 


5. Conclusion


Now you know how to integrate Download CSV functionality in your application which is pretty simple.  Let me know in the comments if it's working for you or not. Happy Learning!! ☺

How to add jQuery datetimepicker in the page?

Today we would be looking at the jQuery datetimepicker implementation. It improves the User Experience. One needs to make a few things in mind for datetimepicker integration like
  • Adding the required HTML code snippet in the page for selecting the date & time i.e. adding input element of type text  
  • Respective JS & CSS libraries(datetimepicker and jQuery related) should be included in the page
  • Activating the datetimepicker using jQuery or JavaScript 
After configuring the datetimepicker, it would look like below:


Implementation:


<html>
<head>
<title>Datetimepicker Demo</title>
<!–– Respective JS & CSS libraries(datetimepicker and jQuery related) should be included in the page ––>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jquery-datetimepicker/2.5.20/jquery.datetimepicker.min.css" rel="stylesheet"/> 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery-datetimepicker/2.5.20/jquery.datetimepicker.full.min.js"></script>
<script>
$(document).ready(function () {
   // Activating the datetimepicker using jQuery or JavaScript 
   $('#datetimepicker1').datetimepicker(); //default    
   $('#datetimepicker2').datetimepicker({ //customized
      format:'d/m/Y H:i',
      minDate:0,
      formatTime:"h:i a",
      step:10,
      // if one would like to take user selected input from datetimepicker and atomatically round off to nearest integral of 10 minutes
      onChangeDateTime:function(dp,$input){
      //27/10/2019 12:01 -> dateTime[0] = date, dateTime[1] = time
 var dateTime = $input.val().split(" "); 
 var time = dateTime[1].split(":");
 var hour = time[0];
 var minutes = time[1];
 var datetimestring;
    
 if(minutes > 0 && minutes < 10) {
         datetimestring = dateTime[0] + ' ' + hour + ':' + 10;
         $input.val(datetimestring);
  }
    ...
  } // end of onChangeDateTime function
   });
   
});
</script>
</head>
<body>
<!–– Adding the required HTML code snippet in the page for selecting the date & time i.e. adding input element of type text  ––>
Default Datetimepicker:
<input type="text" id="datetimepicker1" placeholder="select date time">
Customized Datetimepicker:
<input type="text" id="datetimepicker2" placeholder="select date time">
</body>
</html>

Hoping that it would help you. Happy Learning!! ☺

Thursday, October 10, 2019

th:block tag in Thymeleaf

While designing and developing a Thymeleaf template, have you ever faced a problem of adding unnecessary HTML tag just for holding any conditional statements or an iterative statement which you won't prefer to use if you design the same page statically? Let me give you an example: using <div> blocks inside <table> for iteration purpose only, it might work but it would add an unnecessary empty HTML tag. Don't worry Thymeleaf has a solution for this type of use case. One could use Thymeleaf's provided Synthetic th:block tag. Today we would be discussing th:block tag with some example.

1. th:block tag


  • It's an element processor included in the Standard Dialects. Don't confuse this with an attribute as it is not an attribute. 
  • It is a mere attribute container that allows template developers to specify whichever attributes they want. Thymeleaf will execute these attributes and then simply make the block disappear without a trace.

2. th:block tag Implementation Examples


There are many instances where one could use th:block tag while designing the Thymeleaf templates. It would make our Thymeleaf templates more readable and helps in avoiding unnecessary empty HTML tags which are added after processing of Thymeleaf's attributes if we don't use th: block. I would be sharing the use cases where I have used it:
  • when creating iterated tables that require more than one <tr> for each element
    Disclaimer: This example reference is taken from here. I haven't used it.
    <table>
      <th:block th:each="user : ${users}">
        <tr>
            <td th:text="${user.login}"></td>
            <td th:text="${user.name}"></td>
        </tr>
        <tr>
            <td colspan="2" th:text="${user.address}"></td>
        </tr>
      </th:block>
    </table>
    
  • when creating the ordered / unordered list of items
    <ul>
       <th:block th:each="node : ${bookModel.getOrderedSubTopics()}">
         <li th:if="${node eq 'activity'}">
     <input th:id="${node.nodeId}" type="checkbox" th:value="${node.nodeId}">
      <span th:utext="${node.label}">Topic Name</span>    
          </li>
          <li th:if="${node eq 'reading'}">
       <span th:utext="${node.label}">Topic Name</span>    
          </li>
       </th:block>
    </ul>
    
  • when creating a select box when dropdown items are selected or unselected conditionally
     <select>
       <option value="0"></option>
       <th:block th:each="tag : ${tags}">
         <option th:text="${tag.label}" th:if="${itemTags.contains(tag)}" th:value="${tag.tagTypeLabel}" selected>name</option>
         <option th:text="${tag.label}" th:if="not ${itemTags.contains(tag)}" th:value="${tag.tagTypeLabel}">name</option>
        </th:block>
    </select>

3. Conclusion


th:block tag is a very useful tool that could be used while designing and development of Thymeleaf templates. Template developers don't have to unnecessarily complicate their template/page by adding an HTML tag for holding Thymeleaf's attributes if they don't want that HTML tag after execution in their HTML structure.  Hoping that it would help you. Happy Learning!! ☺

How to access Spring beans in Thymeleaf registered at the Spring Application Context?

Thymeleaf allows accessing beans registered at the Spring Application Context in the standard way defined by Spring EL i.e. by using the @beanName syntax, for example:
<div th:text="${@urService.getSomething()}">...</div> 
This could be useful if one wants to expose some utility methods from Java end to Thymeleaf templates.

Disclaimer:
Till now I haven't used this feature in any of my projects but when I came to know about this feature. I thought why not test it whether it really works or not.
For testing purposes, I have added a @Component annotation (org.springframework.stereotype.Component;) in one of my Spring Boot Utility Class and added a test method i.e. getMessage() which simply returns a String. The idea is to make this bean available in the Spring Application Context. After that, I have tried accessing it using the above syntax and it worked.
For reference,
## test Method
public String getMessage() {
   return "pura game hai";
}
## accessing it in Thymeleaf template 
<div th:text="${@utility.getMessage()}">...</div> 
This is fairly easy and might be useful in some scenarios. Happy Learning!! ☺

Wednesday, October 9, 2019

Web context objects: #httpServletRequest & #httpSession in Thymeleaf

Recently while working on a web application developed using Spring Boot & Thymeleaf, I came to know that Thymeleaf provides direct access to #httpServletRequest & #httpSession objects inside a web environment. These objects are also known as Web context objects. Today we would be discussing these objects and their usages with examples.
  • #httpServletRequest: It provides direct access to the javax.servlet.http.HttpServletRequest object associated with the current request.
    ## Usages
    ${#httpServletRequest.getParameter('foo')}
    ${#httpServletRequest.getAttribute('foo')}
    ${#httpServletRequest.getContextPath()}
    ${#httpServletRequest.getRequestName()}
    
    ## use case while using Script Inlining Feature of Thymeleaf
    <script th:inline="javascript" type="text/javascript">
    /*<![CDATA[*/
        ...
        var assignmentId = /*[[${#httpServletRequest.getParameter('assignmentid')}]]*/ 0;
    
    /*]]>*/
    </script>
    
    ## another example 
    <a th:if="${#httpServletRequest.getParameter('assignmentid') != null} and ${#httpServletRequest.requestURI eq '/studentassignment'}" 
       th:href="@{${#httpServletRequest.requestURI}(isbn=${bookModel.isbn},assignmentid=${#httpServletRequest.getParameter('assignmentid')})}"   
       th:text="${'Test Link'}">Test Link</a>
    
  • #httpSession: It provides direct access to the javax.servlet.http.HttpSession object associated with the current request.
    ## Usages
    ${#httpSession.getAttribute('foo')}
    ${#httpSession.id}
    ${#httpSession.lastAccessedTime}
Hoping that it might be useful for you guys. Happy Learning!! ☺

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

How to prevent click on the specified HTML element using CSS, JS or jQuery

Recently I have got a simple requirement of making specified HTML element non-clickable conditionally. I am free to choose how to implement this i.e. either by using CSS, JS, jQuery. Today I would be sharing how I have achieved this. It might be not the best or optimal solution but it worked for me. Let me know what could be another possible solution for this.

Since the requirement was to make some HTML element non-clickable conditionally, I have used both jQuery and CSS to achieve the complete requirement. But I have used CSS property pointer-events: none to prevent the click on the specified HTML element. The pointer-events property defines whether or not an element reacts to pointer events. Here, I used two of its values i.e.
auto : The element reacts to pointer events, like hover and click. This is default
none : The element does not react to pointer events
$('#topicMenu').children('li:not(.selectedTopic)').css("pointer-events","auto"); //making it again clickable
$('#topicMenu').children('li:not(.selectedTopic)').css("pointer-events","none"); //making it non-clickable

Later I came through one more method using jQuery in StackOverflow but haven't verified it if it really works:
$('selector').click(false); //If using jQuery versions 1.4.3+:
$('selector').click(function(){return false;}); //else 
Feel free to share any new way to make the specified HTML element non-clickable. Happy Learning!!

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!!

Wednesday, September 4, 2019

Solve: QTJava.zip was unexpected at this time error occurred while starting ZooKeeper

Recently I have got an error i.e. \QuickTime\QTSystem\QTJava.zip was unexpected at this time. while starting ZooKeeper that comes packaged with Kafka on Windows system. One might face a similar issue while quickly setting up the Kafka Cluster on Windows systems. That's why sharing the solution.

Error:

D:\kafka\kafka_2.12-2.3.0>bin\windows\zookeeper-server-start.bat config\zookeeper.properties
\QuickTime\QTSystem\QTJava.zip was unexpected at this time.

D:\kafka\kafka_2.12-2.3.0>

Solution:

The error was happening due to the spaces in the folder name present in the %CLASSPATH% environment variable. One just needs to remove the spaces and it would work. 

When I used echo %CLASSPATH% command in CMD it showed me below value:
.;C:\Program Files (x86)\QuickTime\QTSystem\QTJava.zip

I just removed the above entry from CLASSPATH environment variable and tried starting the Zookeeper, it worked like charm. 

Somehow the batch script i.e. zookeeper-server-start.bat is unable to handle the spaces in the environment variables. For me, it has happened due to the CLASSPATH environment variable, but someone might get an error if they have space containing entries in their PATH or JAVA_HOME environment variable. 

Happy Learning!! Let me know if you face this issue and if this solution worked for you also in the comments section. 


Friday, August 17, 2018

How to Start and Access Jenkins in Windows?

Today we would be discussing how to start & access Jenkins in Windows systems. It won't take a minute to get it working. After reading this, one would be able to answer below questions:

Q1: How to start & access Jenkins in Windows using default port i.e. 8080?
Q2: How to start Jenkins on the desired port in Windows?
Q3: What is the default credentials for Jenkins after installation? 

Let's get started.
Step1: Download the latest Jenkins WAR(jenkins.war) from the official site.
Step2: Run the below commands at Command prompt
# run at default port i.e. 8080
java -jar jenkins.war
# run at desired port, use http or https
java -jar jenkins.war --httpPort=8081
java -jar jenkins.war --httpsPort=8081
Step3: Access Jenkins
If you are running the Jenkins in your local environment then hit http://localhost:8081/ in your browser. You would see the Jenkins Home Page screen:
At the top right corner, you will see the option for login & sign up. Let's login using the default admin account. Click on 'log in' link to navigate to the Jenkins Log In Page:

You must be wondering from where we would get the username & password.
username: admin
password: .jenkins/secrets/initialAdminPassword  [Jenkins home directory=$user.home/.jenkins]
Jenkins After Sign In 

Hoping that now you have running Jenkins. Start exploring it. Happy Learning!! :-)

Reference:

[1]: https://wiki.jenkins.io/display/JENKINS/Starting+and+Accessing+Jenkins

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. 

Thursday, May 24, 2018

How to install & configure the AWS CLI on Windows system

One can easily use AWS Management Console to manage their AWS services but if one wants to access & manage their AWS services programmatically then one could install & configure AWS CLI. Today we would be discussing, how to install & configure AWS CLI in Windows systems.
Table Of Content:
1. Introductions
2. Installing the AWS CLI
3. Configuring the AWS CLI
4. Conclusion

Wednesday, May 23, 2018

JBoss Deployment Error: java.lang.LinkageError: loader constraint violation

Getting deployment errors are inevitable. One can't escape from it. Recently I have got a deployment error i.e. java.lang.LinkageError: loader constraint violation while deploying my Maven based application in JBoss. Good news is, I have solved this issue. Along with the root cause of the issue and it's solutions, today we would also discuss the approach that I have used to solve this issue because using similar approach one could troubleshoot many other similar issues.

Let me share the technology stack and deployment logs first before getting in much details. Also one information, I haven't got any Maven error while building the application.

1. Technology Stack


- JDK 7
- Apache Maven 3.5.2
- JBoss-6.1.0.Final

2. Deployment Logs

16:06:22,202 INFO  [TomcatDeployment] deploy, ctxPath=/QuartzScheduler
16:06:22,249 INFO  [[/QuartzScheduler]] QuartzInitializer: Quartz Initializer Servlet loaded, initializing Scheduler...
16:06:22,249 ERROR [[/QuartzScheduler]] StandardWrapper.Throwable: java.lang.LinkageError: loader constraint violation: when resolving method "org.slf4j.impl.StaticLoggerBinder.getLoggerFactory(
)Lorg/slf4j/ILoggerFactory;" the class loader (instance of org/jboss/classloader/spi/base/BaseClassLoader) of the current class, org/slf4j/LoggerFactory, and the class loader (instance of org/jboss/cl
assloader/spi/base/BaseClassLoader) for resolved class, org/slf4j/impl/StaticLoggerBinder, have different Class objects for the type taticLoggerBinder.getLoggerFactory()Lorg/slf4j/ILoggerFactory; used
 in the signature
        at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:299) [:1.6.6]
        at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:269) [:1.6.6]
        at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:281) [:1.6.6]
        at org.quartz.impl.StdSchedulerFactory.(StdSchedulerFactory.java:303) [:]
        at org.quartz.ee.servlet.QuartzInitializerServlet.getSchedulerFactory(QuartzInitializerServlet.java:251) [:]
        at org.quartz.ee.servlet.QuartzInitializerServlet.init(QuartzInitializerServlet.java:183) [:]
        at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1208) [:6.1.0.Final]
        at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1108) [:6.1.0.Final]
        at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:3628) [:6.1.0.Final]
        at org.apache.catalina.core.StandardContext.start(StandardContext.java:3851) [:6.1.0.Final]
        at org.jboss.web.tomcat.service.deployers.TomcatDeployment.performDeployInternal(TomcatDeployment.java:294) [:6.1.0.Final]
        at org.jboss.web.tomcat.service.deployers.TomcatDeployment.performDeploy(TomcatDeployment.java:146) [:6.1.0.Final]
        at org.jboss.web.deployers.AbstractWarDeployment.start(AbstractWarDeployment.java:476) [:6.1.0.Final]
        at org.jboss.web.deployers.WebModule.startModule(WebModule.java:118) [:6.1.0.Final]
        at org.jboss.web.deployers.WebModule.start(WebModule.java:95) [:6.1.0.Final]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [:1.7.0]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) [:1.7.0]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [:1.7.0]
        at java.lang.reflect.Method.invoke(Method.java:601) [:1.7.0]
        at org.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:157) [:6.0.0.GA]
        at org.jboss.mx.server.Invocation.dispatch(Invocation.java:96) [:6.0.0.GA]
        at org.jboss.mx.server.Invocation.invoke(Invocation.java:88) [:6.0.0.GA]
        at org.jboss.mx.server.AbstractMBeanInvoker.invoke(AbstractMBeanInvoker.java:271) [:6.0.0.GA]
        at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:670) [:6.0.0.GA]
        at org.jboss.system.microcontainer.ServiceProxy.invoke(ServiceProxy.java:206) [:2.2.0.SP2]
        at $Proxy41.start(Unknown Source)  

3. Analyzing the Logs


Logs are true saviour for any developer. If one could analyze the logs properly more then more than half of the job is already done. See the highlighted part of the above logs, we have got some useful information about the error:
- the error was due to method resolution as the class loader of the current class and the class loader for the resolved class have different class objects.
- also the error was related to slf4j jar

But wait, have I used slf4j related jar as my dependency in POM.xml? 
The answer would No. Although I have used log4j as my direct dependency in POM.xml but I haven't used slf4j related any jar as my direct dependency in POM.xml.

Then again two questions arises if we though about the cause of the error,
Q1: My application must be getting slf4j related jar as indirect dependency from somewhere which is conflicting with JBoss libraries at run time. Is it so or not?
Q2: Is it because of two libraries i.e. log4j & slf4j, JBoss is throwing Linkage error at run time? 

Therefore if we have to find the exact jar from the application which has slf4j related jar as its indirect dependency and exclude it from that jar then problem should get solved. Let's try out this.

4. Solution

  • Find out the dependency tree of the application
    One could use mvn dependency:tree command to get the dependency tree of any Maven projects. Let's run it and see the output. See, quartz related jar has slf4j-api jar as it's indirect dependency.
    mvn dependency:tree
    
    Output:
    
    ------------------------------------------------------------------------
    Building QuartzScheduler_Maven 1.0-SNAPSHOT
    ------------------------------------------------------------------------
    [dependency:tree]
    com.anshulsblog:QuartzScheduler_Maven:war:1.0-SNAPSHOT
    +- javax.transaction:javax.transaction-api:jar:1.2:provided
    +- org.quartz-scheduler:quartz:jar:2.2.1:compile
    |  +- c3p0:c3p0:jar:0.9.1.1:compile
    |  \- org.slf4j:slf4j-api:jar:1.6.6:compile
    +- log4j:log4j:jar:1.2.17:compile
    \- junit:junit:jar:4.10:test
       \- org.hamcrest:hamcrest-core:jar:1.1:test
    ------------------------------------------------------------------------
    BUILD SUCCESS
    ------------------------------------------------------------------------
    Total time: 2.181 s
    Finished at: 2018-05-22T16:41:58+05:30
    Final Memory: 9M/22M
    ------------------------------------------------------------------------
  • Dependency Exclusion in Maven
    Let's exclude slf4j-api jar from quartz then again build & deploy the application and see whether it solves the issue.
    <dependency>
     <groupId>org.quartz-scheduler</groupId>
     <artifactId>quartz</artifactId>
     <version>2.2.1</version>
            <exclusions>
      <exclusion>
         <groupId>org.slf4j</groupId>
                       <artifactId>slf4j-api</artifactId>
                    </exclusion> 
            </exclusions>
    </dependency>
    
    Built and deployed the application again, it worked and now the deployment logs are clean. 

5. Conclusion


Even though, if one doesn't get any kind of Maven errors while building the application, it doesn't imply that the application would be successfully deployed always. One could get many deployment errors either due to multiple versions of the same jars(direct & indirect dependencies) or due to multiple jars conflict or due to jar conflict between the container's jar and compile time provided jar. In all such instances, it's better to go through the dependency tree of the project (use  mvn dependency:tree command) and if any conflicts found then exclude it. Happy Learning!!



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

Thursday, May 10, 2018

Thymeleaf: jQuery/JavaScript function call with or without parameters (Examples)

While developing our web application, it's very common use case to execute JavaScript functions on an account of any event like onblur, onchange, onclick, onkeydown, onmouseover etc [1]. These calls may be with or without parameters depending upon the business requirement.
             Today, we would see some examples to understand how to properly call JavaScript functions from Thymeleaf. But before that, we would also see used tech stack, Thymeleaf dependencies in the POM file and how we have added page fragments containing our CSS &  JS files in the target HTML page where we would be making the JavaScript function calls.



1. Tech Stack:


- Spring Boot 1.5.10.RELEASE
- Maven 3.3.9
- Thymeleaf 3.0.3.RELEASE

2. Thymeleaf Dependencies in Maven POM file

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
 <groupId>org.thymeleaf</groupId>
 <artifactId>thymeleaf</artifactId>
 <version>3.0.3.RELEASE</version>
</dependency>
<dependency>
 <groupId>org.thymeleaf</groupId>
 <artifactId>thymeleaf-spring4</artifactId>
 <version>3.0.3.RELEASE</version>
</dependency>
<dependency>
 <groupId>nz.net.ultraq.thymeleaf</groupId>
 <artifactId>thymeleaf-layout-dialect</artifactId>
 <version>2.1.2</version>
</dependency>

3. Add external JavaScript file to the HTML page


For cleanliness and better maintainability, I have kept almost all of my JavaScript functions in a separate JS file which is located at <project_name>/src/main/resources/public/js/main.js and then added the fragment containing CSS & JS in HTML file using th:replace attribute.

3.1 The Fragment 

## <project_name>/src/main/resources/templates/fragments/header.html
<head th:fragment="cssandjs">
 <title>Anshul's Blog</title>
 <link rel="stylesheet" type="text/css" th:href="@{/css/screen.css}"/>
 
 <script type="text/javascript" src="https://code.jquery.com/jquery-latest.min.js"></script>
 <script type="text/javascript" th:src="@{/js/main.js}" src="/js/main.js"></script>
</head>

3.2 The Target HTML page 


This is the file where we have added the cssandjs fragment using th:replace attribute and will be making JavaScript calls using Thymeleaf. For more details on th:replace attribute, have a look at this write-up.
## <project_name>/src/main/resources/templates/target.html
<head th:replace="fragments/header :: cssandjs">

4. jQuery / JavaScript Function Calls


Apart from function calls, we would also see situations where we may avoid writing JavaScript functions. One might confuse while making function calls as when to directly use events like onclick, onchange etc or use Thymeleaf's attributes like  th:onclick or th:onchange etc. Therefore, just follow the golden rule i.e. use Thymeleaf's attributes only when, we need to pass some dynamic values in the functions otherwise stick with normal HTML event attributes. Now we ready to fly, everything is in place.

4.1 Function call without parameter

<button onclick="addItemToKart()">Add Item</button>
<div class="close"><span id="x" onclick="closeItemDetailsInModelWindow()">&#9747;</span></div>
<select th:name="${#strings.listSplit(stream.key,',')[1]}" 
  th:onchange="${#strings.listSplit(stream.key,',')[1] == 'Science'} ? 'populateScienceOrCommerceDropdown()' : ''">

4.2  Function call with parameters

## ${item.id} is of type Integer
<input type="button" value="Select" th:onclick="|showItemDetailsInModelWindow(${item.id})|"/>

## ${author.id} is of type Integer & ${author.name} is of type String
<input type="button" value="Show books by author" th:onclick="|showBooksByAuthor(${author.id}, '${author.name}')|"/>

## ${titleModel.isbn} is of type String & ${book.bookId} is of type Integer
<a th:onclick="|bookDetails('${titleModel.isbn}',${book.bookId})|" style="cursor: pointer;">Book Details</a> 

4.3 Avoid writing JavaScript functions


In some situations, one could avoid writing JavaScript functions like when one have to simply call a particular controller's method or when one have to show the popup box [Alert box, Confirm box, and Prompt box] etc.
<button th:onclick="'javascript: document.location=\'/chapterdetails?isbn=' + ${bookModel.isbn} + '&amp;page=1\''"></button>  
<input type="submit" value="Approve" onclick="return ( prompt('You must type APPROVED to continue') == 'APPROVED' )" /> 

5. Conclusion 


Now we know how to make JavaScript function calls in Thymeleaf. We have also seen how to keep function calls in a separate file for better maintainability and then use th:replace attribute to add the fragments containing these CSS & JS files. Happy Learning!!

Appendix:
[1] : Some examples of event attribute and their corresponding event actions:
  • onclick Event:
    onclick of a button, invoke a controller method with or without parameter
    - onclick of a button, open a model window to either show some information to user or to take user's input
  • onchange Event:
    dynamically showing different select box on selecting different values from a select box 

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

Thursday, May 3, 2018

Difference between Thymeleaf attribute th:replace, th:insert and th:include

Similar to JSP includes, Thymeleaf offers page fragment inclusion but with some important improvements. One could include parts of other pages as fragments (whereas JSP only includes complete pages ) using th:replace or th:insert or th:include. Although the job of all these three attributes are same but how they actually include parts of pages as fragment in the target page is little bit different. It's very important to understand the back-end processing of this attribute otherwise one would get surprising results. That's why, today we would be discussing difference between these attributes.


Functionality


Before describing the attributes functionalities, be familiar with term like:
Host Tag:  tag containing th:replace, th:insert or th:include attribute [would be present in the target page where one would like to add the fragment]
Fragment Tag: tag containing th:fragment attribute [would be present in any page depending upon the design of the page but generally one would store their fragments in modular fashion like header.html or fragments.html]

th:replace - It will actually substitute the host tag by the fragment’s. That means, It will remove the host tag and in place of host tag, it will add the specified fragment including the fragment tag.

th:insert - It will simply insert the specified fragment as the body of its host tag including the fragment tag.

th:include - It will also insert the specified fragment as the body of its host tag but excluding the fragment tag.

Implementation


We have already provided the functionality overview of each of the attributes but it would be more clear after going through this example. We would be adding the the fragment and see the HTML output that's generated by each of the attribute.

Step 1: Add the fragment in the target page
<div id="tagWithReplaceAttribute" th:replace="fragments/header :: targetFragmentToIncludeInOurPage"></div>
<div id="tagWithInsertAttribute" th:insert="fragments/header :: targetFragmentToIncludeInOurPage"></div>
<div id="tagWithIncludeAttribute" th:include="fragments/header :: targetFragmentToIncludeInOurPage"></div>
where,
fragments/header = a template name that one are referencing to. This can be a file or it can reference to the same file either by using the this keyword (e.g. this :: header) or without any keyword (e.g. :: header).
targetFragmentToIncludeInOurPage = expression after double colon is a fragment selector (either fragment name or Markup Selector)

Step 2: Create the fragment to add

Adding it to [/<project_name>/src/main/resources/templates/fragments/header.html]
<div th:fragment="targetFragmentToIncludeInOurPage" id="tagWithFragmentAttribute">
 <div id="contentGoesHere"></div>
</div>
Step 3: The Output
<div id="tagWithFragmentAttribute">
 <div id="contentGoesHere"></div>
</div>

<div id="tagWithInsertAttribute">
 <div id="tagWithFragmentAttribute">
  <div id="contentGoesHere"></div>
 </div>
</div>

<div id="tagWithIncludeAttribute">
 <div id="contentGoesHere"></div>
</div>
Look at the output, now we know which attribute generates which kind of HTML code after processing. Therefore don't confuse with these attributes and use attributes judiciously depending upon the requirements. Happy Learning!!