24 Ağustos 2010 Salı

Testing JSF Applications by JMeter

JMeter is quite good tool for stress / load testing.In JMeter there are various request types like http request , soap request for testing. These request are sent by threads . Increasing number of threads will increase the load on your application.I will explain how to test JSF applications by JMeter . For regular jsp's it is easier to test becasue there is no jsessionid or another jsf specific parameter.
First I will introduce my web application. It is just a simple login form which is consist of username and password.Run JMeter , first create a thread group. We will add requests,cookie manager and regular expression extractor into the thread group.First retrieve the login form so we can get jsessionid and javax.faces.ViewState input.


As you can see I defined servername, serverport and address of page.Then we will add cookie manger for jsessionid.


Cookie Manager is added and rfc2109 is selected as a cookie policy.Now we have to add regular expression extractor for javax.view.state parameter.If you don't retrieve this value and post it , your action will be failed.



Now we have to post username , password and some jsf specific data .It is similar to the first request. Parameter names should be encoded.


In the end add "View Result Tree" so you can see request and response .

15 Ağustos 2010 Pazar

Dynamic Rescheduling by Spring-Quartz

Spring supports Quartz so you can easily create batch jobs. These jobs may be triggered in time intervals or cron expressions. In context xml you can define these attributes. I want to explain how to change dynamically these definitions ,which is read from context xml.

First how to define a quartz job in context.xml ...You have to define JobDetailBean,SimpleTriggerBean and SchedulerFactoryBean :

<bean name="scheduledJob" id="scheduledJob" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="com.blogspot.devside.quartz.job.ScheduledJob"/>
</bean>


<bean id="trigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="jobDetail" ref="scheduledJob"/>
<property name="startDelay" ref="2000" />
<property name="repeatInterval" ref="2000"/>
</bean>

<bean id="schedulerFactory" name="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" scope="singleton">
<property name="triggers">
<list>
<ref bean="trigger"/>
</list>
</property>
</bean>



And our ScheduledJob class .It will only print current time in seconds.

public class ScheduledJob extends QuartzJobBean{

static SimpleDateFormat format = new SimpleDateFormat("hh:mm:ss");
@Override
protected void executeInternal(JobExecutionContext arg0)
throws JobExecutionException {
System.out.println("Scheduled job - Current Millis : " + format.format(new Date(System.currentTimeMillis())) );
}
}

Then we need Runny class which has a main method.

public class Runny {
public static void main(String[] args) throws InterruptedException {
ApplicationContext ctx =
new ClassPathXmlApplicationContext("/applicationContext.xml");
}
}


If you run the runny class, you will see the result , looks like the following lines.

Scheduled job - Current Millis : 10:51:27
Scheduled job - Current Millis : 10:51:29

Scheduled job - Current Millis : 10:51:31
Scheduled job - Current Millis : 10:51:33
Scheduled job - Current Millis : 10:51:35
...


Now we have a quartz job which runs in every 3 seconds. 3 seconds time interval is defined in context xml . It is static. Now what if we want to retrieve time interval value from a database or another source and change it dynamically.

First , we have to get the value from a bean (bean can get value from database , web service,etc...) ,we will use method invocation for this.
Second , we will change repeatInterval and startDelay . SchedulerFactoryBean will be singleton so we can get trigger and change its values.

Our new context xml will be like the following lines :

<bean id="scheduledJobDef" name="scheduledJobDef" class="com.blogspot.devside.quartz.job.ScheduledJobDef"/>


<bean id="rescheduler" name="rescheduler" class="com.blogspot.devside.quartz.Rescheduler">

<property name="schedulerFactory" ref="schedulerFactory"></property>
<property name="scheduledJobDef" ref="scheduledJobDef"></property>
</bean>

<bean name="scheduledJob" id="scheduledJob" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="com.blogspot.devside.quartz.job.ScheduledJob"/>
</bean>


<bean id="trigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="jobDetail" ref="scheduledJob"/>
<property name="startDelay" ref="startDelayMethod" />
<property name="repeatInterval" ref="repeatIntervalMethod"/>
</bean>

<bean id="schedulerFactory" name="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" scope="singleton">
<property name="triggers">
<list>
<ref bean="trigger"/>
</list>
</property>
</bean>

<bean id="repeatIntervalMethod"

class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject">
<ref local="scheduledJobDef" />
</property>
<property name="targetMethod">
<value>getFirstRepeatInterval</value>
</property>
<property name="arguments">
<list />
</property>
</bean>

<bean id="startDelayMethod"

class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject">
<ref local="scheduledJobDef" />
</property>
<property name="targetMethod">
<value>getFirstStartDelay</value>
</property>
<property name="arguments">
<list />
</property>
</bean>


Scheduled JobDef class :

public class ScheduledJobDef {
public long getFirstStartDelay(){
return 2000;
}

public long getFirstRepeatInterval(){

return 2000;
}

public long getStartDelay(){

return 5000;
}

public long getRepeatInterval(){

return 5000;
}
}



MethodInvocationFactoryBean beans will invoke getFirstStartDelay and getFirstRepeatInterval.

Rescheduler class :

public class Rescheduler {
StdScheduler schedulerFactory;
ScheduledJobDef scheduledJobDef;


public void reschedule(){

System.out.println(schedulerFactory);
try {
SimpleTriggerBean t = (SimpleTriggerBean) schedulerFactory
.getTrigger("trigger", Scheduler.DEFAULT_GROUP);

JobDetail job = schedulerFactory.getJobDetail(t.getJobDetail()

.getName(), t.getJobDetail().getGroup());

t.setRepeatInterval(scheduledJobDef.getRepeatInterval());
t.setStartDelay(scheduledJobDef.getStartDelay());
t.setStartTime(new Date( System.currentTimeMillis()));

schedulerFactory.rescheduleJob(t.getName(), Scheduler.DEFAULT_GROUP, t);

schedulerFactory.start();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

public StdScheduler getSchedulerFactory() {

return schedulerFactory;
}

public void setSchedulerFactory(StdScheduler schedulerFactory) {

this.schedulerFactory = schedulerFactory;
}

public ScheduledJobDef getScheduledJobDef() {

return scheduledJobDef;
}

public void setScheduledJobDef(ScheduledJobDef scheduledJobDef) {

this.scheduledJobDef = scheduledJobDef;
}

}


In reschedule method , trigger retrieved from singleton SchedulerFactoryBean then its values are changed.Trigger is rescheduled and started.

New lines must be added to Runny class ,

public class Runny {


public static void main(String[] args) throws InterruptedException {

ApplicationContext ctx =
new ClassPathXmlApplicationContext("/applicationContext.xml");

Thread.sleep(10000);


Rescheduler rescheduler = (Rescheduler) ctx.getBean("rescheduler");

rescheduler.reschedule();

Thread.sleep(10000);

}
}


There are two sleep because I want to show difference between before and after trigger rescheduled.
System out will look like the following lines :

Scheduled job - Current Millis : 11:09:46
Scheduled job - Current Millis : 11:09:48
Scheduled job - Current Millis : 11:09:50
Scheduled job - Current Millis : 11:09:52
Scheduled job - Current Millis : 11:09:54
org.quartz.impl.StdScheduler@dc57db
Scheduled job - Current Millis : 11:09:54
Scheduled job - Current Millis : 11:09:59
Scheduled job - Current Millis : 11:10:04
..

As you can see , after reschedule progress is done , time interval changed as 5 seconds.