Template Engines for Java WebApps (Velocity Vs FreeMarker Vs Thymeleaf Vs Rythm)

In many projects, developed using Java technologies Java Server Pages (JSPs) was the standard for the presentation layer for a long time. Among many other things JSPs has the features of a template processor. The biggest shortcoming of this technology is the possibility to insert business logic in the presentation code. Thus, we can insert into the JSP document scriptlets or even Java code blocks. Although this can help us in certain situations, the code becomes rapidly complex and hard to maintain. Because of shortcomings such as this one, JSP lost many followers in favor of other template engines, which are used in more and more projects, increasing the developers" productivity and the quality of the products.

In this article I will try to analyse four popular template engines available freely for commercial use. The four template engines are Apache Velocity, FreeMarker, Thymeleaf and Rythm.

Introduction

Velocity is a project distributed under the Apache Software License, which benefits from great popularity among the Java applications developers. Like other template engines, Velocity was designed to enable the webmasters and the Java developers to work in parallel.

FreeMarker is a product that has reached maturity, distributed under a BSD license. Similar to the Apache Velocity project, FreeMarker offers complex functionalities designed for assisting web developers. It was designed for efficiently generating HTML pages, and not only that. Furthermore as the creators of the project state, this is a generic software product that can be used for text generation, ranging from HTML to source code.

Thymeleaf is a Java library distributed under the ٢nd version of Apache License with the main goal to create templates in an elegant way. The most suitable use case for Thymeleaf is generation of XHTML / HTML٥ documents within a web context. However this tool can be used in offline environments as well, being able to process XML documents.

Rythm is a template engine for Java applications distributed under the Apache License version 2.0 and described by its author as being a general purpose product, easy to be used and super-fast. Similarly to other template processors, we can process with it HTML documents, XML documents, SQL scripts, source code, emails and any other kind of formatted text. Rythm was inspired by the .Net Razor project, due to its simple and elegant syntax.

Template Language

Apache Velocity enjoys its own scripting language called Velocity Template Language (VTL) which is powerful and flexible. The authors of Apache Velocity proudly advertise that their product"s flexibility is limited only by the user"s creativity. VTL was created to offer the simplest and cleanest way for inserting dynamic content into a web page.

FreeMarker provides us with a strong templating language, called FreeMarker Template Language. With FTL we can define expressions, functions and macros within the templates that we write. Furthermore, we also have the possibility to use a rich library with predefined directives that give us the possibility to iterate data collections, include other templates, and much more.

Thymeleaf relies on a set of features called a dialect. The standard distribution comes with the Standard dialect and the SpringStandard dialect which allow us to create so-called natural templates. These can be correctly displayed by the browser even when we access them as static files. Consequently these documents can be viewed as prototypes.

Rythm was inspired by the .Net Razor project, due to its simple and elegant syntax. Rythm uses the special character @ to introduce all syntax elements.

Performances

Using Apache HTTP server benchmarking tool on machine with following specs:

Mac OS X Version 10.11.1
2,3 GHz Intel Core i7 Quad core
ava(TM) SE Runtime Environment (build 1.8.0_51-b16)
Java HotSpot(TM) 64-Bit Server VM (build 25.51-b03, mixed mode)
Apache Tomcat 7.0.53 with 512M RAM

Total time taken for processing 25.000 requests with a concurrency level of 25. (lower is better)
We optain following results:

Thymeleaf               4.147 seconds
Freemarker              2.637 seconds
Velocity                2.491 seconds
Rythm                   1.991 seconds

Conclusions

Both Velocity and FreeMarker are established products, which proved their worth in many successful projects offering decent performance. On the other hand Thymeleaf and Rythm are young projects that come with a new philosophy adapted to the current trends in web development. For instance, Thymeleaf excels at natural templating, while Rythm offers a clean syntax, easy to understand both for programmers and webmasters. We can conclude that choosing a template engine depends first of all on the project we need it for.
Read More

EHCache : Implementation of Java in-memory object cache

The in-memory caching system is designed to increase application performance by holding frequently-requested data in memory, reducing the need for database queries to get that data. For One of application requirement, I need a Java in-memory object caching that can replace HashMap based caching system. I need to extend the cache to include basic features like max size and time to live but don't bother about caching server or persistence.

Example of Cache

I have investigated following options:
  • Guava CacheBuilder - active development. See this presentation.
  • LRUMap - Config via API. No TTL. Not purpose built for caching.
  • whirlycache - XML config. Mailing list. Last updated 2006.
  • cache4j - XML config. Documentation in Russian. Last updated 2006.
I found that  EHCache is very nice where I can create an in memory cache. I have checked out their code samples for an example of creating an in memory cache. I can specify a max size, and a time to live, it is really awesome. EHCache does offer some advanced features, but if your not interested in using them - don't. But it's nice to know they are there if your requirements ever change.

Ehcache is an open source, standards-based cache that boosts performance, offloads your database, and simplifies scalability. It's the most widely-used Java-based cache because it's robust, proven, full-featured, and integrates with other popular libraries and frameworks.

 So let discuss the implementation part of EHCache in your application. First, we need to download the ehcache-core-2.6.2.jar, slf4j-api-1.6.1.jar and slf4j-jdk14-1.6.1.jar in ehcache-core-2.6.2-distribution.tar.gz from http://ehcache.org/downloads. Then, add this jar in the librairies folder of your project \war\WEB-INF\ or in your pom.xml (MAVEN).

Configuration ehcache.xml
Create (this file could be copied from downloaded package) an ehcache.xml file in the classpath of your project. This file contains a default Cache configuration with an implicit name “default” which is a reserved cache name. This cache will be applied to caches created programmatically (using CacheManager.add(String cacheName)).
So, we will add a sample cache named “myCache1” wich will contain a maximum in memory of 10000 elements, and will expire an element if it is idle for more than 5 minutes (300 sec) and lives for more than 10 minutes (600 sec). If there are more than 10000 elements it will overflow to the disk cache, which in this configuration will go to wherever java.io.tmp is defined on your system. On a standard Linux system this will be ‘/tmp’, for Windows7 it could be ‘C:\Users\username\AppData\Local\Temp’.

Find the sample configuarion code:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="ehcache.xsd"
         updateCheck="true" monitoring="autodetect"
         dynamicConfig="true">


    <diskStore path="java.io.tmpdir"/>

    <defaultCache
            maxEntriesLocalHeap="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            diskSpoolBufferSizeMB="30"
            maxEntriesLocalDisk="10000000"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU"
            statistics="false">
        <persistence strategy="localTempSwap"/>
    </defaultCache>

    <cache name="myCache1"
           maxEntriesLocalHeap="10000"
           maxEntriesLocalDisk="1000"
           eternal="false"
           diskSpoolBufferSizeMB="20"
           timeToIdleSeconds="300"
           timeToLiveSeconds="600"
           memoryStoreEvictionPolicy="LFU"
           transactionalMode="off">
        <persistence strategy="localTempSwap"/>
    </cache>
    
</ehcache>
 How to Implement in Application?
  •  First, we will create an utilitary class named CacheUtil in order to manipulate and sollicit the Ehcache
  • Get the cache instance of Ehcache via the method getCache. This method could be synchronized.

public static CacheManager cacheMgr = null;

private static Ehcache getCache(String cacheName){
 if(cacheMgr == null){
  // We could use an environment or a VM variable
  cacheMgr = CacheManager.create("...\\config\\ehcache.xml");
 }
  
 Ehcache cache = null;
 if(cacheMgr!=null){
  //cache = cacheMgr.addCacheIfAbsent(name);
  cache = cacheMgr.getEhcache(cacheName);
 }
 
 return cache;
}
  •  Get data from the cache via the method getListFromCache.
@SuppressWarnings("unchecked")
public static <T> List<T> getListFromCache(String threadName, String cacheName, String key, CacheCreation<T> cacheCreation){
 List<T> all = new ArrayList<T>();
  
 Ehcache cache = getCache(cacheName);
 Element element = null;
 if(cache!=null){
  element = cache.get(key);
 }
  
 if(element==null){
  System.out.println(threadName+" : CacheUtil.getListFromCache() : the element '"+key+"' has not been found in the cache ---> get the original data.");

  all = cacheCreation.getAll();
  cache.put(new Element(key, all));
  System.out.println(threadName+" : CacheUtil.getListFromCache() : the original data for the element '"+key+"' has been added in the cache.");


 }else{
  System.out.println(threadName+" : CacheUtil.getListFromCache() : the element '"+key+"' has been found in the cache.");

  //all = (List<T>) element.getValue();
  all = (List<T>) element.getObjectValue();
 }
 return all;

} 

  •  We have also created an abstract class CacheCreation to in anticipation of the use of cache: 

public abstract class CacheCreation<T> { 
 public abstract List<T> getAll(); 
}
  • Then, we will create an class UseCaseClass to use and check the Ehcache containing main method to create several threads soliciting the Ehcache: 
public static void main(String[] args) {
 int nbThreads = 3;
 ExecutorService execService = Executors.newFixedThreadPool(nbThreads);
  
 // Create several threads which solicit the Ehcache
 for (int i = 0; i < nbThreads; i++) {
  final int indexFinal = i;

  execService.submit(new Runnable(){
   String threadName= null;
   UseCaseClass useCaseClass = null;
    
   public void run(){
    try {
     useCaseClass = new UseCaseClass();
     threadName = "thread_"+indexFinal;
     useCaseClass.getAllData1(threadName);
     {
      int sleepTime = getRandomSleepTime(1000, 5000);
      System.out.println(threadName+" will sleep during "+sleepTime+"ms.");
      Thread.currentThread().sleep(sleepTime);
      System.out.println(threadName+" wakes up");
     }
     useCaseClass.getAllData2(threadName);
     {
      int sleepTime = getRandomSleepTime(1000, 5000);
      System.out.println(threadName+" will sleep during "+sleepTime+"ms.");
      Thread.currentThread().sleep(sleepTime);
      System.out.println(threadName+" wakes up");
     }
     useCaseClass.getAllData1(threadName);
     useCaseClass.getAllData2(threadName);
     useCaseClass.getAllData1(threadName);
     useCaseClass.getAllData2(threadName);
    } catch (Throwable e) {
     e.printStackTrace();
    }
     
   }//end-run
    
   private int getRandomSleepTime(int min, int max){
    return min + (int)(Math.random() * ((max - min) + 1));
   }

  }//end-runnable

  );//end-submit

 }//end-for
}

  • The Ehcache will be sollicited by 2 methods getAllData1 and getAllData2:
          
 public static void main(String[] args) {
 int nbThreads = 3;
 ExecutorService execService = Executors.newFixedThreadPool(nbThreads);
  
 // Create several threads which solicit the Ehcache
 for (int i = 0; i < nbThreads; i++) {
  final int indexFinal = i;

  execService.submit(new Runnable(){
   String threadName= null;
   UseCaseClass useCaseClass = null;
    
   public void run(){
    try {
     useCaseClass = new UseCaseClass();
     threadName = "thread_"+indexFinal;
     useCaseClass.getAllData1(threadName);
     {
      int sleepTime = getRandomSleepTime(1000, 5000);
      System.out.println(threadName+" will sleep during "+sleepTime+"ms.");
      Thread.currentThread().sleep(sleepTime);
      System.out.println(threadName+" wakes up");
     }
     useCaseClass.getAllData2(threadName);
     {
      int sleepTime = getRandomSleepTime(1000, 5000);
      System.out.println(threadName+" will sleep during "+sleepTime+"ms.");
      Thread.currentThread().sleep(sleepTime);
      System.out.println(threadName+" wakes up");
     }
     useCaseClass.getAllData1(threadName);
     useCaseClass.getAllData2(threadName);
     useCaseClass.getAllData1(threadName);
     useCaseClass.getAllData2(threadName);
    } catch (Throwable e) {
     e.printStackTrace();
    }
     
   }//end-run
    
   private int getRandomSleepTime(int min, int max){
    return min + (int)(Math.random() * ((max - min) + 1));
   }

  }//end-runnable

  );//end-submit

 }//end-for
}






Read More

JqueryUI Autocomplete

Autocomplete is a technique used in modern websites to suggest a list beginning with few character that user typed in text box. The user can select an item from the list to complete the word or sentence.

jQueryUI provides the autocomplete() method to create a list of suggestions below the input field and adds new CSS classes to the elements concerned to give them the appropriate style.

Syntax

The autocomplete() method can be used in two forms:
  • $(selector, context).autocomplete (options) Method
  • $(selector, context).autocomplete ("action", params) Method

$(selector, context).autocomplete (options) Method

The autocomplete (options) method declares that an HTML <input> element must be managed as an input field that will be displayed above a list of suggestions. The options parameter is an object that specifies the behavior of the list of suggestions when the user is typing in the input field.

Syntax

$(selector, context).autocomplete (options);
You can provide one or more options at a time using Javascript object. If there are more than one options to be provided then you will separate them using a comma as follows:
$(selector, context).autocomplete({option1: value1, option2: value2..... }); 

$(selector, context).autocomplete ("action", params) Method

The autocomplete ("action", params) method can perform an action on the list of suggestions, such as show or hide. The action is specified as a String in the first argument (e.g., "close" to hide the list).

Syntax

$(selector, context).autocomplete ("action", params);

Example


   <script>
         $(function() {
            var dataSource = [
               "Java",
               "Boostrap",
               "C",
               "Bitspi",
            ];
            $( "#automplete" ).autocomplete({
               source: dataSource 
            });
         });
      </script>
     <div class="ui-widget">
         <input id="automplete">
     </div>
Read More

JAVA Framework for Artificial Intelligence, Machine Learning or Neural Network

Encog

Encog Machine Learning Framework is an advanced machine learning framework that supports a variety of advanced algorithms, as well as support classes to normalize and process data. Machine learning algorithms such as Support Vector Machines, Artificial Neural Networks, Genetic Programming, Bayesian Networks, Hidden Markov Models, Genetic Programming and Genetic Algorithms are supported. Most Encog training algoritms are multi-threaded and scale well to multicore hardware. Encog can also make use of a GPU to further speed processing time.

It was written by Jeff Heaton in the early 90s, and was the standard Java DL framework for a long time. I do not believe that Encog handles distributed computing, works with GPUs, Hadoop, Spark or Kafka, or takes into account many of the algorithmic advances in DL since 2006.

Neuroph 

Neuroph is lightweight Java neural network framework to develop common neural network architectures. It contains well designed, open source Java library with small number of basic classes which correspond to basic NN concepts. Also has nice GUI neural network editor to quickly create Java neural network components.
Neuroph is VERY focused on neural networks and you can express a connection between just about anything. For very custom/non-standard neural networks of different typologies than the typical Elman/Jordan, NEAT, HyperNEAT, Feedforward type networks, then Neuroph will fit the bill nicely.

Deeplearning4J

Deeplearning4j is the first commercial-grade, open-source, distributed deep-learning library written for Java and Scala. Integrated with Hadoop and Spark, DL4J is designed to be used in business environments, rather than as a research tool. Skymind is its commercial support arm.

It works on distributed CPUs or GPUs using Spark as an access layer. It's certified on CDH5 and soon on HDP... And it includes implementations of LSTMs (RNNs), deep convolutional nets, RBMs, DBNs and word2vec, among other neural nets. It is currently the most popular DL tool for the JVM, and one of the top 5 DL libraries in the world.

Deeplearning4j is powered by the numerical computing lib ND4J, or n-dimensional arrays for Java. Basically, they ported Numpy to the JVM. That makes DL4J extensible, and they are planning to add other algos like reinforcement learning in the near future. ND4J, in turn, runs on libND4J, a C++ library that makes the computation fast. They also built the vectorization library, Canova, that takes any type of data and turns it into a vector that neural nets can understand. They are also trying to solve some of the ETL problems upstream from NNs.

Read More

Levenshtein Distance in Java - Fuzzy Logic to match names or any strings

Levenshtein Distance is a well-known algorithm that takes two strings and returns an integer representing the number of changes that need to be made to one string in order to have it transformed to the second string.

Apache Commons Lang library already has a method in the StringUtils class for this called getLevenshteinDistance. That’s nice to know so that you don’t have to implement your own. You can use the Levenshtein Distance to perform “fuzzy matching” between two strings with a calculation like:

percentMatch = 1 – (levenshteinDistance / longestStringLength) * 100

The “longestStringLength” is the length of the longer of the two strings (use something like Math.max(a.length(), b.length())).
Read More

Quartz Scheduler with Spring 4

Spring provides couple of classes that simplify the usage of Quartz within Spring-based applications.

There are 2 ways to configure a Job in Spring using Quartz:

A : Using MethodInvokingJobDetailFactoryBean

    This is the simplest among two.


<!-- For times when you just need to invoke a method on a specific object -->
<bean id="simpleJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
    <property name="targetObject" ref="myJobBean" />
    <property name="targetMethod" value="myMethod" />
</bean>

Above job configuration simply invokes myMethod method of bean myJobBean which is simple POJO

B : Using JobDetailFactoryBean

When you need more advanced setup, need to pass data to job, being more flexible.
<!-- For times when you need more complex processing, passing data to the scheduled job -->
<bean name="complexJobDetail"    class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
    <property name="jobClass" value="com.websystique.spring.quartz.ScheduledJob" />
    <property name="jobDataMap">
        <map>
            <entry key="anotherBean" value-ref="anotherBean" />
        </map>
    </property>
    <property name="durability" value="true" />
</bean>


 Also there are two method to configure trigger:

Trigger defines the time when scheduler will run your scheduled job. There are two possible trigger type:
A: Simple Trigger , using SimpleTriggerFactoryBean
You can specify start time, delay between triggers and repeatInterval(frequency) to run the job.

<!-- Run the job every 2 seconds with initial delay of 1 second -->
<bean id="simpleTrigger"  class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
    <property name="jobDetail" ref="simpleJobDetail" />
    <property name="startDelay" value="1000" />
    <property name="repeatInterval" value="2000" />
</bean>
B: Cron Trigger , using CronTriggerFactoryBean
It’s more flexible and allows you to choose scheduled job at specific instance (time, day, date,..) and frequency in future.

<!-- Run the job every 5 seconds only on Weekends -->
<bean id="cronTrigger"  class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
    <property name="jobDetail" ref="complexJobDetail" />
    <property name="cronExpression" value="0/5 * * ? * SAT-SUN" />
</bean>
 
SchedulerFactoryBean glues together jobDetails and triggers to Configure Quartz Scheduler

<!-- Scheduler factory bean to glue together jobDetails and triggers to Configure Quartz Scheduler -->
<bean  class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="jobDetails">
        <list>
            <ref bean="simpleJobDetail" />
            <ref bean="complexJobDetail" />
        </list>
    </property>
    <property name="triggers">
        <list>
            <ref bean="simpleTrigger" />
            <ref bean="cronTrigger" />
        </list>
    </property>
</bean>


 
Read More

A Beginner's Guide to EJB

The Java EE specifications defines a standard mechanism for Java EE applications, which is known as Java EE platform. The platform uses a component based approach to provide a multitiered, distributed, transactional model for enterprise applications. A component is a unit of functionality that is assembled, along with any required resources, and it can communicate with another component inside the Java EE environment or in a networked, multi-machine, distributed environment.

In Simple word Enterprise Java Bean (EJB) is a component that is managed by EJB Container inside Application Server like Websphere, JBoss, Weblogic etc and can be invoked by another component on the same  machine or, more typically, somewhere on the network.

These components come in three varieties, each with its own defined role and life cycle:

Session beans - These may be either stateful or stateless, and are primarily used to encapsulate business logic, carry out tasks on behalf of a client, and act as controllers or managers for other beans.

Entity beans - Entity beans represent persistent objects or business concepts that exist beyond a specific application's lifetime; they are typically stored in a relational database. Entity beans can be developed using bean-managed persistence,which is implemented by the developer, or container-managed persistence, implemented by the container.

Message-driven beans - Message-driven beans listen asynchronously for Java Message Service (JMS) messages from any client or component and are used for loosely coupled, typically batch-type, processing.

Session bean

Session beans are reusable components that have conversations or sessions with clients, it can be invoked by local, remote or webservice client and primarily used to encapsulate business logic.

There are 3 types of session bean.
  • Stateless Session Bean: It doesn't maintain state of a client between multiple method calls.
  • Stateful Session Bean: It maintains state of a client across multiple requests.
  • Singleton Session Bean: One instance per application, it is shared between clients and supports concurrent access.

Stateless Session Bean

Stateless session beans do not maintain conversational state and remember nothing from previous client interaction, but it may preserve its instance state. EJB Container normally creates a pool of few stateless bean's objects and use these objects to process client's request. Because of pool, instance variable values are not guaranteed to be same across method calls.

There are only two milestones in a stateless session bean's life cycle: Does Not Exist and Ready. EJB Container creates and maintains a pool of session bean first. It injects the dependency if any, then calls the @PostConstruct method if any. Now actual business logic method is invoked by the client. Then, container calls @PreDestory method if any. Now bean is ready for garbage collection.

Example of Stateless Session Bean

Remote Interface
import javax.ejb.Remote;
@Remote
public interface HotelSessionBeanRemote {
  void bookRoom(Integer roomNo, String custName);
}
Stateless EJB
@Stateless
public class HotelSessionBean implements HotelSessionBeanRemote { 
Map room = new HashMap();
void bookRoom(Integer roomNo, String custName){
 room.put(roomNo, custName);
}

Stateful Session Bean

Stateful session beans are called "stateful" because they maintain a conversational state with the client. In other words, they have state or instance fields that can be initialized and changed by the client with each method invocation. The bean can use the conversational state as it process business methods invoked by the client. 

Example of Stateful Session Bean

Remote Interface
import javax.ejb.Remote;
@Remote
public interface BankSessionBeanRemote {
  void bookRoom(Integer roomNo, String custName);
}
Stateful EJB
@Stateless
public class BankSessionBean implements HotelSessionBeanRemote { 
Map room = new HashMap();
void bookRoom(Integer roomNo, String custName){
 room.put(roomNo, custName);
}
 
 
Read More

Latest EJB Question and Answer

1- What is EJB ?
EJB stands for Enterprise JavaBean and is a widely-adopted server side component architecture for J2EE. It enables rapid development of mission-critical application that are versatile, reusable and portable across middleware while protecting IT investment and preventing vendor lock-in.

2- What is session Facade?
Session Facade is a design pattern to access the Entity bean through local interface than accessing directly. It increases the performance over the network. In this case we call session bean which on turn call entity bean.

3- What is EJB role in J2EE?
EJB technology is the core of J2EE. It enables developers to write reusable and portable server-side business logic for the J2EE platform.

4- What is the difference between EJB and Java beans?
EJB is a specification for J2EE server, not a product; Java beans may be a graphical component in IDE

5- What are the key features of the EJB technology?
1. EJB components are server-side components written entirely in the Java programming language
2. EJB components contain business logic only – no system-level programming & services, such as transactions, security, life-cycle, threading, persistence, etc. are automatically managed for the EJB component by the EJB server.
3. EJB architecture is inherently transactional, distributed, portable multi-tier, scalable and secure.
4. EJB components are fully portable across any EJB server and any OS.
5. EJB architecture is wire-protocol neutral–any protocol can be utilized like IIOP,JRMP, HTTP, DCOM,etc

6- Are enterprise beans allowed to use Thread.sleep()?
Enterprise beans make use of the services provided by the EJB container, such as life-cycle management. To avoid conflicts with these services, enterprise beans are restricted from performing certain operations: Managing or synchronizing threads

7- Is it possible to write two EJB’s that share the same Remote and Home interfaces, and have different bean classes? if so, what are the advantages/disadvantages?
It’s certainly possible. In fact, there is  an example that ships with the Enterprise Application Server of an Account interface with separate implementations for Checking Account and Savings Account, one of which was CMP and one of which was BMP

8- Is it possible to specify multiple JNDI names when deploying an EJB?
No. To achieve this you have to deploy your EJB multiple times each specifying a different JNDI name.

9- Is there any way to force an Entity Bean to store itself to the db? We can’t  wait for the container to update the db, we need to do it NOW! Is it possible?
Specify the transaction attribute of the bean as RequiresNew. Then as per section 11.6.2.4 of the EJB v 1.1 spec EJB container automatically starts a new transaction before the method call. The container also performs the commit protocol before the method result is sent to the client.
Read More