Showing posts with label Tomcat. Show all posts
Showing posts with label Tomcat. Show all posts

Sunday, 19 August 2012

Managing PermGen and Heap allocations in Tomcat7

If you are developing a web-application that runs on Tomcat 7, it is highly likely that you will encounter a PermGen space error on Tomcat which happens when you deploy and undeploy the application several times and there is a memory leak. There could be several reasons for a memory leak and they could stem from loading third-party jars such as JDBC drivers and logger jars from within the web-application lib. To overcome some of these potential issues, it is best to load them directly into Tomcat lib and let Tomcat the Driver Manager take care of de-registering them when not in use.

While the best approach to dealing with this problems and other memory related problems is debugging the cause of the memory leak and fixing it, there are times when tuning the JVM parameters can alleviate the cause and improve performance of the application to a certain extent.

Before diving into the tuning the JVM parameters, it is important to understand how JVM organises its memory space and what is the difference between heap and permgen space and how they are used. This article gives a very good overview of the JVM memory layout.  To summarise the difference between the two, the permgen space is used to store classes loaded by the class loader, primitives,any static classes and other JVM related data. On the other hand, the heap space is mainly used to store objects created by the application. It is further divided as explained here into Eden, Survivor and Tenured Gen space.

It is also important to note that since Java 1.6 update 16, there have been some major changes to the process used to compute heap size in 32 bit and 64 bit JVMs and in client / server mode.

Having understood the basics of JVM memory organisation, we can look at tuning Tomcat's memory allocation for its heap and permgen. While there are several parameters that can be used for tuning the JVM, this post is just going to describe the minimum and maximum parameters for specifying the heap and the permgen space. The location of where to specify these parameters and their values depends on your machine specification (operating system, memory size, 32 bit or 64 bit) and how you invoke Tomcat.

Deciding on the actual values of the parameters should be taken after monitoring the JVM using some tools such as jVisualVM. The values given below are sample values that worked in my particular case.

Case 1: Tomcat is invoked from within Eclipse on a 32 bit machine.
Specs : Tomcat 7.0.28, Eclipse Juno, Sun Java 1.6.30, Windows 7.0

The parameters should be specified in Server Launch Configuration -> Open Launch Configuration -> Edit Launch Configuration Properties ->Arguments
Tomcat Launch Configuration in Eclipse
The detailed steps are available here.

Case 2: Tomcat is invoked via its start up script on a 32 bit virtual machine.
Specs : Tomcat 7.0.28, Sun Java 1.6.30, Ubuntu 12.04

Create a setenv.sh file and add the following one line in it.

export JAVA_OPTS="-Dfile.encoding=UTF-8 -server -Xms128m -Xmx256m -XX:MaxPermSize=128m -XX:+DisableExplicitGC"

Transfer this file to your Tomcat/bin directory and re-start Tomcat.

There are a number of ways of verifying that the JVM parameters were applied to Tomcat. The easiest way on Ubuntu is : ps -ef | grep tomcat

You should see something similar to the line below:

john     17841     1  5 15:23 pts/0    00:00:09 /usr/bin/java -


Djava.util.logging.config.file=/usr/local/apache-tomcat/conf/logging.properties -Xms128m -Xmx256m -XX:MaxPermSize=128m -XX:+DisableExplicitGC -
Djava.endorsed.dirs=/usr/local/apache-tomcat/endorsed -classpath /usr/local/apache-tomcat/bin/bootstrap.jar:/usr/local/apache-tomcat/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/apache-tomcat -Dcatalina.home=/usr/local/apache-tomcat -Djava.io.tmpdir=/usr/local/apache-tomcat/temp org.apache.catalina.startup.Bootstrap start



With respect to parameter values for the heap, it is important to note that :

(Managed Heap + native heap + (thread stack size * number of threads)) cannot exceed 2GB on 32bit x86 Windows or Linux systems (ref)


2GB is a theoretical limit. Since the heap requires contiguous memory space, it might be hard to push the heap beyond 1.4GB on a 32 bit Windows machine.

A final comment.
The JVM is an intelligent software and has several inbuilt processes built into it that work to optimize its performance. Attempting to tune the JVM may not always result in a performance improvement. Tuning the JVM is dependent on the machine specification, the design decisions taken behind the architecture of the web-application it is hosting, the number of applications hosted by the JVM and when all else fails, Trial and Error. 

Tuesday, 24 July 2012

Monitor your Tomcat Server with Psi-Probe

Psi-Probe is an excellent Tomcat and JBOSS server monitoring tool. Setting it up is as easy as uploading the application, which comes packaged as a WAR file. Before setting it up, create a user with the role probeuser, in your conf/tomcat-users.xml.
Psi-Probe allows you to manage and monitor the server's health (memory usage, cpu usage, OS and server information) as described in the screenshot below.
PSI-Probe Memory Monitoring Console

Psi-Probe also allows you to restart the server JVM and kill threads. Another interesting feature of Psi-Probe is that you can see which jsps are not being used by the application. These jsps get tagged with the status 'outdated' while the jsps which are being used by the application  have a status of 'compiled'. Further, you can also manage requests based on session IDs and monitor the average response time.

Thursday, 19 January 2012

Setting up a database based authentication realm in Tomcat 7.0.0

Setting up an authentication module is one of the primary tasks that come across a web-developer's canvas when coding a web-application.In this post, I'll detail the basic steps needed to set up a database backed authentication realm and outline the configuration files that need to be updated when using a Tomcat 7.0.0 servlet container. This post is NOT about security or securing the web-app context so please if you do implement these steps, please do some more research on what is required to secure your web-application.It is also important to note that this post pertains to Tomcat version 7.0.0 and some steps may not be required in more recent versions.
Tomcat 7.0.0 implements the Servlet 3.0 specification (JSR 315) which provide login / logout methods to be invoked on the HttpServletRequest. 
Step 1: Create the user and user-roles table in your database using the sql scripts described here. Insert a couple of records in each table.
Step 2: Set up Tomcat to connect to the database realm
(a) In the context.xml(located in server/conf directory), set up the datasource  
    
(b) In server.xml (located in server/conf directory) add the following snippets in the correct location within the xml file. This will set up the connection between the datasource and the authentication mechanism :


.......

..........








Step 3: Download the jdbc driver based on your database & the tomcat-jdbc jar to set up the JDBC Connection Pool (You do not need to download the tomcat-jdbc jar if you are using Tomcat version 7.0.19 and above).


Step 4: Write the logic for passing the login & password from the user form to the backing bean.
 public String login() {  
          FacesContext context = FacesContext.getCurrentInstance();  
          HttpServletRequest request = (HttpServletRequest) context  
                                             .getExternalContext().getRequest();  
             
          try 
          {  
               request.login(username, password);  

          } catch (ServletException e) {  
            e.printStackTrace();
               context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Login   failed!", null));  
               return "failed-login";  
          }  
             
 //You can fetch user from database for authenticated principal and do some action  
          Principal principal = request.getUserPrincipal();  
          log.info("Authenticated user: " + principal.getName());  
             
             
          if(request.isUserInRole("administrator")) {  
            setLoginSectionVisible(false);
            setUploadSectionVisible(true);
            context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Login successful!", null));  
               return "admin-login";  
          } else {  
               return "user-login";  
          }  
     }  

Saturday, 19 November 2011

Tomcat 7.0, JSF (Mojarra) 2.3.1 and PrimeFaces 3.0M4


Spent the last few nights experimenting with the bleeding edge of Java Server Faces (JSF), Prime Faces and Tomcat and expectedly came away bloody and a lot more wiser.

Java Server Faces has come a long way in the last 5 years or so but a steep learning curve and relatively poor documentation makes it even harder to adapt. The latest specification release of JSF is 2.1, compatible with JavaEE 6 application servers, or any server implementing Servlet 3.0.JSF has two main implementation flavours- Apache MyFaces and Sun (now Oracle 's) Mojarra.

Now herein lies the problem.There are some subtle differences between JSF 2.0 and 2.1 specifications as pointed out by BaluC. JSF 2.1 is aimed at marrying the Servlet 3.0 API and so targets Servlet Containers supporting the 3.0 specification, such as Tomcat 7.0, Glassfish v3. while JSF 2.0 was aimed at the Servlet specification 2.5 and so works well with earlier releases of the servers.

If you are intending to use the latest release of Tomcat which is 7.0.22 and JSF MyFaces, you should be fine but if you try and bring in a component library such as Tomahawk, you'll find that support for the > JSF 2.0 version of a JSF implementation is not all there.I decided to use PrimeFaces and went with 3.0M4, a milestone release from last week and while the setup and integration of the stack (Tomcat 7.0.22, MyFaces 2.3.1 (and later I removed MyFaces and bought in Mojarra) was smooth(Thanks to Maven), getting the FileUpload component of PrimeFaces to work was impossible. The fileUpload bean would just not get called and there were no errors in the server log. Baffling!!Questions to the user forum did not show much light until I came upon Bug 49711 related to annotation scanning in the Tomcat archives. The problem was not with PrimeFaces of a JSF implementation but with a regression of Tomcat's handling of a multi-part request. This problem was reported since version 7.0.6 and while there is an indication that setting allowCasualMultipartParsing = true in the Context definition will by-pass this issue, I can tell you otherwise. Anyway, I got it all to work with Tomcat 7.0.2 (i.e I had to go back 20 releases).

Tomcat version 7.0 onwards implements the Servlet 3.0 specification and brings in some new and very much needed features such as out-of-the box authentication support(via the HttpRequest) and FileUpload. This major leap forward could have possibly led to these regression defects that need to be addressed before Tomcat can be regarded as a stable candidate for implementing a JSF based stack. JSF (MyFaces & Mojarra) doesn't really help Tomcat in the sense that itself is in a state of evolution and the component libraries are struggling to keep up.

To end on a positive note, I was very impressed by the PrimeFaces showcase and the extensive set of features offered which currently makes it one of the best JSF component libraries going around.However, again a word of caution.The last stable release of version PrimeFaces is 2.2.1 which has Flash based components while the latest 'milestone' version 3.0M4 is based on HTML5.This again is a major revamp of the architecture and currently the forum is littered with support questions and reports of 'not working', so wait for a few more releases before choosing PrimeFaces version 3+ or like me, prepare for battle!!

Thursday, 10 November 2011

Deploying your web application to TomCat 7.0 using Maven

Deploying your web-application using the tomcat-maven-plugin can be done by as follows:
1. Create a user in Tomcat with the manager-script role. Before Tomcat 7.0, this was accomplished using the manager role. The user details can be sepecifed in the conf/tomcat-users.xml file as follows:
2. Now you need to tell maven that it can deploy applications to Tomcat using this role.
To set this connection, open your settings.xml file which should be present .m2 directory. Search for 'server' and put in the following credentials:

          localhost
          tom
          cat

Obviously, the server name is :localhost in this case.
3. In your maven pom.xml configure the tomcat-maven-plugin as follows:

             org.codehaus.mojo
             tomcat-maven-plugin
             
                http://localhost:8080/manager/text
                      localhost
                      /test
             
         

Take note of the
http://localhost:8080/manager/text
This is important otherwise you will keep getting 403:Access Forbidded errors when you attempt to deploy.
  • To build you war and deploy on Tomcat, use : mvn tomcat:deploy
  • To redploy your war, use : mvn tomcat:redeploy
  • To undeploy your war, use : mvn tomcat:undeploy
Troubleshooting : If you are getting connection refused : 401 errors while deploying, it means that most probably you have not setup your Maven settings.xml file correctly or that you have added the configuration parameters to the wrong file.