Showing posts with label spring. Show all posts
Showing posts with label spring. Show all posts

Monday, November 18, 2013

JMeter Tutorial - Writing a Test Plan

In this tutorial, we will write a very simple test plan.

Here are the specs of the Test Application we will run JMeter against:

  • large instance on EC2
  • Ubuntu LTS12.04
  • Tomcat 7
  • Java and Spring


Setting up JMeter on Windows

We will be setting up JMeter on Windows simply because it's easier. Read User Load Testing Simulation - Installing Apache JMeter on Windows 2012 Base.


Creating a Thread Group

Start JMeter by clicking on bin/ApacheJMeter.jar in your install location. You will see in the Tree hierarchy that it has a Test Plan item and a WorkBench item.

Right click on Test Plan -> Add -> Threads (Users) -> Thread Group

The Thread Group tells JMeter how many users and requests it should simulate.

In the Thread Group panel, fill in the following:

Name: Web Users
Number of Threads (users): 10
Ramp-Up Period (in seconds): 0
Loop Count: 5

The above will generate 5 requests for each of the 10 users. Total number of requests is 50.

The Ramp-Up Period defines the time delay which each JMeter will start the user. If Ramp-Up Period is 10 and Number of Threads is 10 then the delay between each user is 1 second. In the above, we have Ramp-Up Period = 0, meaning that all the users will start at the same time.


Add Default HTTP Request Information

Since most requests we are going to make will share some common properties (like IP and port), we will set up some default HTTP Request Information.

Right click on Web Users -> Add -> Config Element -> HTTP Request Defaults.

Fill in your server name (or IP) and port number.


Add Cookies

We will add HTTP Cookies.

Right click on Web Users -> Add -> Config Element -> HTTP Cookie Manager


Adding a HTTP Request

This is where your simulated users will request. We will add a login request. You will need to figure out what are your site's username and password parameters (In my case, it's username and password)

Right click on Web Users -> Add -> Sampler -> HTTP Request

Fill in the following:

Name: Login
Server Name of IP: /
Method: POST

In parameters, click Add.

Add Name=username, Value={your_username}
Add Name=password, Value={your password}

You can add a GET a request similarly as well.


Adding the Graph Results Listener

To observe response time, we can add the Graph Results Listener.

Right click on Web Users -> Add -> Listener -> Graph Results.


Running the Test Plan

In the menu bar, click on Run -> Start

Monday, November 4, 2013

Enable Async Request Processing for Java Spring

Serlvet 3 supports asynchronous request processing which allows the requested operation to be performed on a separate thread, freeing the HTTP request memory.

In Spring, an allocated amount of memory is allocated for request processing. If you are running a long operation (such as uploading a large file, batch mailing, big data analysis), the memory for that request would be blocked until the operation is finished.

A better way of approaching this would be to return the request right away and let the long operation to run in another thread.

In Spring 3.x, it is relatively easy with the @Async support.

Before I dive down into the tutorial, here's my specs:
  • ubuntu 12.04
  • large EC2 instance
  • OpenJDK 1.7
  • Maven 3.0.4
  • Spring 3.2.4
  • CXFServlet 2.5.3 with JAX-RS (This is for Rest API)
This post will be about how to enable @Async in your spring project.


Install the latest version of Spring

At the time of this writing, the stable version is 3.2.4. The following shows how to add the maven dependency in pom.xml



Use Serlvet 3.0 namespace

In web.xml, make sure you use the XML nameplace for version 3.0.

 


Add Async Support in entry servlets in web.xml

If you are writing a normal Spring MVC Web app, you will need to add async-supported in the dispatcher serlvet below. My project only uses the Rest API, so I put the async-supported xml tag in the CXFServlet.



Enable Async in application context

In applicationContext.xml, enable executor and scheduler. If you don't know where is the applicationContext.xml, find it from web.xml's contextConfigLocation context-param field.


Make sure you have the task namespace as above.


Annotate a method as @Async

Below is a quick test of the @Async method. Notice the @Async annotation below.


Try taking out the @Async annotation and execute the program. You should be able to observe the difference.

Wednesday, October 2, 2013

ElasticSearch - Indexing via Java API

There are many ways to populate your data to the ElasticSearch data store. The most primitive way is to populate via the REST API via PUT or POST requests.

In this tutorial, we will be populating via the Java API. I have data in MySQL and my Web application is based on Spring.

Here's my setup:

  • Ubuntu 12.04 Amazon EC2
  • JDK 1.7
  • Spring 3.2
  • MySQL


Install ElasticSearch (ES) via Maven

Put the following into your pom.xml file.

Make sure you also installed the same version of ES on your server. Read How to Install ElasticSearch on EC2.

Let's create a search service called ElasticSearchService:

Interface:



Implementation:

We will be using the ElasticSearch's native Java API. We will connect to the ElasticSearch cluster using the Client object. Using the XContentBuilder, we can construct JSON wrapper of the category objects. The category data is stored in MySQL and retrieved by the categoryDao object. Finally, a HTTP GET request will put the data into the ES cluster.



Let's create the interface that you can invoke the call.

Interface:



Implementation:

Wednesday, June 19, 2013

Building a JAR Executable with Maven and Spring

I have a Spring MVC web project. I want to generate some xml files based on some data stored in my database. This program will be run once or a few times everyday. As the data size grows, the program may take longer to run. The best way to do this is to write a JAR executable and feed it to Amazon to Elastic MapReduce.

We will set up a small JAR project with Maven below.

First generate a Maven project called maventest. If you do not have maven set up, read Install Maven 3 on Amazon EC2 Ubuntu.
mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DgroupId=com.mycompany.maventest -DartifactId=maventest
Resources files are located in src/main/resources/.

Spring requires a context xml file that defines how classes are instantiated. Create a file called applicationContext.xml in src/main/resources.

Paste the following into the applicationContext.xml file



Create a file called jdbc.properties in src/main/resources. We will be connecting to a MySQL database.



My whole project is called myproject. It has the Spring MVC web project has the package name   com.mycompany.package1 and artifactId mywebproject. This cron program will have the package name com.mycompany.package2 with artifactId cron.

We will use the maven-jar-plugin to define the location of our main class.

< plugin>
< groupId>org.apache.maven.plugins< /groupId>
< artifactId>maven-jar-plugin< /artifactId>
< configuration>
  < archive>
    < manifest>
      < mainClass>com.mycompany.package2.App< /mainClass>
    < /manifest>
  < /archive>
< /configuration>
< /plugin>

In order to package all the dependencies as one jar file, we will use maven-shade-plugin. Sometimes, spring.schemas and spring.handlers files can be overwritten. Examine the transformers tag below to see that the content of these files will be appended.

We will now include all the dependencies in the pom.xml file.


Package the project (It's useful to understand what's compile, package, install and deploy)
mvn clean package
If the package command fails, it may be complaining that it can't find the com.mycompany.package1.mywebproject project.

You can do a mvn:install for mywebproject. This will install mywebproject to the local maven repository. It is located under /Users/{your_name}/.m2. Remember to compile mywebproject as JAR by setting it in the pom.xml. If you ever suspect that some classes are missing or the build is not quite correct. It's highly likely that mywebproject in the local repository is not up-to-date.

The jar file is located in the target folder. Run the jar
java -jar maventest-1-0-SNAPSHOT

Tuesday, June 18, 2013

Spring component-scan: scanning services from multiple base packages

In your applicationContext.xml, you can specify base packages for scanning by:


<context:component-scan base-package="com.mycompany.package1, com.mycompany.package2"/>

Wednesday, June 12, 2013

Java Spring Profiling with Spring Insight

We will be using Spring Insight to profile a Spring MVC application in Amazon EC2. As long as you are using Ubuntu, you should be able to follow this post.

Specs:
  • Ubuntu Server 12.04.1 LTS
  • m1.small instance
  • a pre-existing Java Spring application deployed on tomcat7
  • Java Open JDK 1.7
Being by connecting to you machine via ssh.

Download Spring Insight. Select the vfabric tc server developer edition instead of the springsource tool suite (STS). You will need to sign on an account in the VMware website. Use wget to fetch the file to your ubuntu instance.
wget {link to vfabric-tc-server-developer-2.9.2.RELEASE.zip}
cd /opt
mkdir /opt/tools
cd /opt/tools
unzip vfabric-tc-server-developer-2.9.2.RELEASE.zip
mv vfabric-tc-server-developer-2.9.2.RELEASE
Inside the vfabric-tc-server-developer-2.9.2.RELEASE folder, run
./tcruntime-instance.sh create insight -t insight
You will see
Creating instance 'insight' ...
  Using separate layout
  Creating bin/setenv.sh
  Applying template 'base'
    Copying template's contents
    Applying fragment 'context-fragment.xml' to 'conf/context.xml'
    Applying fragment 'server-fragment.xml' to 'conf/server.xml'
    Applying fragment 'web-fragment.xml' to 'conf/web.xml'
    Applying fragment 'tomcat-users-fragment.xml' to 'conf/tomcat-users.xml'
    Applying fragment 'catalina-fragment.properties' to 'conf/catalina.properties'
  Applying template 'base-tomcat-7'
    Copying template's contents
    Applying fragment 'server-fragment.xml' to 'conf/server.xml'
    Applying fragment 'web-fragment.xml' to 'conf/web.xml'
    Applying fragment 'catalina-fragment.properties' to 'conf/catalina.properties'
  Applying template 'insight'
    Copying template's contents
    Applying fragment 'server-fragment.xml' to 'conf/server.xml'
  Configuring instance 'insight' to use Tomcat version 7.0.39.B.RELEASE
  Setting permissions
Instance created
Connector summary
  Port: 8080   Type: Auto-Switching HTTP 1.1   Secure: false
A folder called insight is created.

If you change into the insight directory, you will see a folder called webapps (this is almost same as the Tomcat directories). Copy your war file into this directory.
cd insight
cp {your_java_war_file} webapps/
Start the insight instance.
./tcruntime-ctl.sh insight start
You will see
Using CATALINA_BASE:   /opt/tools/vfabric-tc-server-developer-2.9.2.RELEASE/insight
Using CATALINA_HOME:   /opt/tools/vfabric-tc-server-developer-2.9.2.RELEASE/tomcat-7.0.39.B.RELEASE
Using CATALINA_TMPDIR: /opt/tools/vfabric-tc-server-developer-2.9.2.RELEASE/insight/temp
Using JRE_HOME:        /usr/lib/jvm/java-7-openjdk-amd64/jre
Using CLASSPATH:       /opt/tools/vfabric-tc-server-developer-2.9.2.RELEASE/insight/bin/insight-bootstrap-tomcat-extlibs-1.9.2.SR1.jar:/opt/tools/vfabric-tc-server-developer-2.9.2.RELEASE/tomcat-7.0.39.B.RELEASE/bin/bootstrap.jar:/opt/tools/vfabric-tc-server-developer-2.9.2.RELEASE/tomcat-7.0.39.B.RELEASE/bin/tomcat-juli.jar
Using CATALINA_PID:    /opt/tools/vfabric-tc-server-developer-2.9.2.RELEASE/insight/logs/tcserver.pid
Status:                RUNNING as PID=503
Be sure to open port 8080 in your security group.

Now browse to the webpage.
http://{external_ec2_address}:8080/{war_name}

Tuesday, February 12, 2013

Spring - Could not open Hibernate Session for transaction

This happens when the Spring application is idle for a while and a user tries to log in to the application.

The message is as follows:
Could not open Hibernate Session for transaction; nested exception is org.hibernate.TransactionException: JDBC begin failed
 Subsequent logins after the first login failure would sucede.

This has to do with stale database connections. There are connections killed by the server that are still considered to be alive by the connection pool.

There are two solutions:

  1. set minimum connection pool size to zero
  2. set "testonborrow"
"testonborrow" will also test if the connection is alive prior to issuing the desired query.

To implement any of the above, you can use c3p0 or Apache's dbcp library.

The following will demonstrate "testonborrow":

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="maxActive" value="100"/>
        <property name="maxWait" value="1000"/>
        <property name="poolPreparedStatements" value="true"/>
        <property name="defaultAutoCommit" value="true"/>
        <property name="validationQuery" value="SELECT 1" />
        <property name="testOnBorrow" value="true" />
</bean>