Wednesday, January 18, 2012

Jersey-Spring Integration

If you don't plan to use spring, look at a simple Jersey application without spring integration here. 

This article shows basic code to integrate spring with Jersey. Jersey has the ability to convert a JAXB annotated class to xml. This code is also included.

Create a new web application and  add jersey-core-1.1.5.jar, jersey-server-1.1.5.jar, jersey-client-1.1.5.jar, jsr311-api-1.1.1.jar, asm-3.1.jar, jersey-spring-1.1.5, ,jaxb-api-2.2.jar,jaxb-impl-2.2.3-1.jar
to WEB-INF/lib.
package com.mycompany.rest;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.springframework.stereotype.Component;

@Component
@Path("/helloWorld")
public class HelloWorld {
 @GET
 @Produces(MediaType.TEXT_PLAIN)
 public String plainHelloWorld() {
   return "Hello World";
 }

@GET
@Produces(MediaType.TEXT_XML)
public Person sayXMLHello() {
   Person person = new Person();
   person.setAge(29);
   person.setFirstName("harish");
   person.setLastName("Choragudi");
   return person;
 }

@GET
@Produces(MediaType.TEXT_HTML)
public String htmlHelloWorld() {
  return " " +  "" + "Hello World" + "" + " ";
}
}


package com.mycompany.rest;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Person {
   private String firstName;
   private String lastName;
   private Integer age;
public String getFirstName() {
    return firstName;
}
public void setFirstName(String firstName) {
    this.firstName = firstName;
}
public String getLastName() {
    return lastName;
}
public void setLastName(String lastName) {
    this.lastName = lastName;
}
public Integer getAge() {
    return age;
}
public void setAge(Integer age) {
    this.age = age;
}
 
}


The client to test the service

package com.mycompany.rest;

import java.net.URI;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;

public class RestClient {
    public static void main(String[] args) {
        ClientConfig config = new DefaultClientConfig();
        Client client = Client.create(config);
                //Http basic authentication 
        client.addFilter(new HTTPBasicAuthFilter("username","password"));
        WebResource service = client.resource(
          UriBuilder.fromUri( "http://localhost:9085/testapplication").build());
      
        System.out.println(service.path("rs").path("helloWorld").accept(
                MediaType.TEXT_PLAIN).get(ClientResponse.class).toString());
        // Get plain text
        System.out.println(service.path("rs").path("helloWorld").accept(
                MediaType.TEXT_PLAIN).get(String.class));
        // Get XML
        System.out.println(service.path("rs").path("helloWorld").accept(
                MediaType.TEXT_XML).get(String.class));
        // Get HTML
        System.out.println(service.path("rs").path("helloWorld").accept(
                MediaType.TEXT_HTML).get(String.class));

    }
}

In Web.xml
<context-param>
        <description></description>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>

       
<listener>
        <description></description>
        <display-name>AppInit</display-name>
        <listener-class>
              org.springframework.web.context.ContextLoaderListener
        </listener-class>
</listener>

<servlet>
        <servlet-name>Jersey REST Service</servlet-name>
        <servlet-class>
              com.sun.jersey.spi.spring.container.servlet.SpringServlet
        </servlet-class>
       <init-param>  
          <param-name>  
            com.sun.jersey.config.property.resourceConfigClass   
          </param-name>    
          <param-value>  
             com.sun.jersey.api.core.ClasspathResourceConfig   
          </param-value>  
       </init-param>  
       <init-param>  
         <param-name>  
            com.sun.jersey.config.property.classpath   
         </param-name>    
         <param-value>
            WEB-INF/lib
         </param-value>  
    <!-- Use WEB-INF/lib if you have your Service class in a jar file. 
      WEB-INF/classes is used if you have your service classes in class folder 
      of your web application  
    -->
       </init-param>  
       <load-on-startup>1</load-on-startup>
</servlet>
   
<servlet-mapping>
    <servlet-name>Jersey REST Service</servlet-name>
    <url-pattern>/rest/*</url-pattern>
 </servlet-mapping>


If you don't have   com.sun.jersey.config.property.resourceConfigClass  param value set the exception below is thrown. So make sure you set it.
com.sun.jersey.api.container.ContainerException: The ResourceConfig instance does not
contain any root resource classes.
If you use spring  make sure you use <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class> instead of  <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> 

A simple jersey application

Create a new web application and  add jersey-core-1.1.5.jar, jersey-server-1.1.5.jar, jersey-client-1.1.5.jar, jsr311-api-1.1.1.jar, asm-3.1.jar  to WEB-INF/lib.


package com.mycompany.rest;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/helloWorld")
public class HelloWorld {

  @GET
  @Produces(MediaType.TEXT_PLAIN)
  public String plainHelloWorld() {
    return "Hello World";
  }

    @GET
    @Produces(MediaType.TEXT_XML)
    public String xmlHelloWorld() {
        return "<?xml version=\"1.0\"?>" + "<hello> Hello World </hello>";
    }
   
   
   
@GET
   @Produces(MediaType.TEXT_HTML)
    public String htmlHelloWorld() {
        return "<html> " +  "<body>" + "Hello World" + "</body>" + "</html> ";
    }

}

The client to test the service

package com.mycompany.rest;

import java.net.URI;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;

public class RestClient {
    public static void main(String[] args) {
        ClientConfig config = new DefaultClientConfig();
        Client client = Client.create(config);
                //Http basic authentication  
        client.addFilter(new HTTPBasicAuthFilter("username","password"));
        WebResource service = client.resource(UriBuilder.fromUri( "http://localhost:9085/testapplication").build());
       
        System.out.println(service.path("rs").path("helloWorld").accept(
                MediaType.TEXT_PLAIN).get(ClientResponse.class).toString());
        // Get plain text
        System.out.println(service.path("rs").path("helloWorld").accept(
                MediaType.TEXT_PLAIN).get(String.class));
        // Get XML
        System.out.println(service.path("rs").path("helloWorld").accept(
                MediaType.TEXT_XML).get(String.class));
        // Get HTML
        System.out.println(service.path("rs").path("helloWorld").accept(
                MediaType.TEXT_HTML).get(String.class));

    }
}

In web.xml:
 
<servlet>
   <servlet-name>RESTFUL SERVICE</servlet-name>
   <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
   <load-on-startup>1</load-on-startup>
</servlet>
   
<servlet-mapping>
    <servlet-name>RESTFUL SERVICE</servlet-name>
    <url-pattern>/rs/*</url-pattern>
</servlet-mapping>
   

The endpoint you are looking for is http://localhost:9085/testapplication/rs/helloWorld


Monday, January 9, 2012

Two-Phase Commit Transactions for J2EE Applications

Two-phase commit (also known as XA, which is a protocol for two-phase commit) protocol is a method for coordinating J2EE global transactions. In other words, when data is modified across multiple resources, the XA protocol ensures that transactional updates are committed in or rolled back out of all the participating resources, reverting to the state prior to the start of the transaction. Thus, either all the participating resources are updated or none of them are updated. The resource managers have to be XA-enabled to be able to participate in a 2-PC transaction. Since coordination of several resource managers is necessary, the WebSphere Application Server (WAS) uses a transaction manager to coordinate the transaction.

The transaction manager is external to any of the resource managers and is provided by the application server. The transaction manager uses the javax.transaction.xa.XAResource interface to coordinate the 2-PC process. The communication steps between the transaction manager and the resource managers are as follows. Steps 3 and 4 below are the two phases of the commit process.

1.  Start- The transaction manager enlists the resource as part of the transaction. This tells the resource manager to record all future work as part of the transaction.

2.  End -The transaction manager informs the resource manager that no more transaction work is coming its way for this transaction. This is a signal for the resource manager to stop recording. At this point, the resource manager holds the recorded work in a bucket associated with the current transaction ID and waits for further instruction from the transaction manager.

3.  Prepare (Phase 1) -The transaction manager asks all resource managers to prepare to commit their work.  At this moment all the resource managers vote on the outcome of the transaction. If they all respond affirmatively, the transaction is committed. If any resource manager responds negatively,  the whole transaction rolls back.

4.  Commit (Phase 2) -The transaction manager asks all resource managers to either commit or roll back the work done on behalf of the transaction, based on the responses in the prepare phase.

Considerations - XA-Enabled Resources
 As a general guideline use XA-enabled resources if:

•  There may be more than one participant in a transaction (for example, two JDBC databases or a database and a JMS connection). This allows the container to perform any appropriate optimizations if there is only one participant, but to handle XA correctly if there are two or more participants.

•  An EJB needs to access another EJB deployed in a different EJB container, and it is desirable to have both EJBs participate in a single transaction, then both containers should use XA resource managers. The only way to tie the two EJBs together into a single transaction is to use XA resources in both EJBs. This is an example of a distributed transaction; and requires the use of XA resources.

It can be assumed that the container will appropriately manage local vs. global transactions based on the number of participants and that it will perform automatic optimizations.

Performance
It is important to note that using XA-enabled resources degrades performance. The resource access
is between 18-27% slower using an XA resource manager than a non-XA resource manager. However, this is for basic operations; in a real application the cost would be a smaller percentage of the total as compared to the other operations. This difference is enough to be concerned about in performance-critical situations, but not large enough to prohibit the use of XA when it is necessary.


Last Participant Support(LPS)
WebSphere's Last Participant Support (LPS) can be used if the given unit of work needs to access a
resource that does not support 2-PC but can participate in a WebSphere-managed transaction. This is
an advanced capability of the transaction manager to coordinate global transactions involving a number of two-phase commit-capable resource managers and a single one-phase commit-capable resource manager. When a global transaction involving this mix of resources is about to be committed, the transaction manager uses the 2-PC protocol to prepare all two-phase commit-capable resources. If this is successful, the one-phase commit (1-PC) resource is asked to commit the transaction. Depending on the outcome of the one-phase resource commit operation, the two-phase commit resources are then committed or rolled back.

Keep in mind that LPS is not a real transaction and only allows the application to get as close to 2-PC as possible. LPS introduces a hazard of a mixed commit result because 1-PC resources can't completely participate in the 2- PC protocol. For example, if the transaction manager doesn't get a response from the 1-PC resource, it has no way of knowing the status. Therefore, the transaction manager cannot reliably determine the correct outcome of the global transaction on other 2-PC resources. In this case, manual intervention will be required to resolve the state of the data in the 1-PC resource.

Saturday, January 7, 2012

Creating a data datasource (JNDI) in RSA

1) Run Admin Console
2) Go to the "Environment" tab then "Websphere Variables"
3) Add "C:\Program Files\DB2\SQLLIB\java" to both DB2UNIVERSAL_JDBC_DRIVER_PATH and
DB2_JDBC_DRIVER_PATH. Save the changes.
db2jcc.jar, db2jcc_license_cu.jar, db2jcc_license_cisuz.jar need to be in this path
4) Resources ->JDBC ->JDBC Providers-> New
5) Specify the scope as "Node= WPWDCBRNode04, Server= serverl"


6) Fill out the following fields and then click next.
- Database Type- "DB2"
- Provider Type- "DB2 Universal JDBC Driver Provider"
- Implementation Type- "Connection pool data source"
- Name- "DB2 Universal JDBC Driver Provider"

7) Leave the fields blank and click next.


8) Review the summary page and then click "Finish"



9) Click Security> Secure administration, applications, and infrastructure.

10) Under Authentication, click Java Authentication and Authorization Service> J2C authentication data.


11) Create a new authentication alias and Fill out the fields "Alias", "User 10" and "Password" . Apply
and Save.



12) Click the JDBC Provider that was just created.




13) Once the page opens up, under "Additional Properties" click "Data sources" and then click "New"
(Or just go to Resources->JDBC->DataSources and click new to create new datasource. You will be given an option to choose the jdbc provider you created before.)






14) Under "JNDI Name" put "jdbc/testdb". Under component managed authentication alias, select the
previously created authentication alias.


15) Click "Next" and fill out the fields, click "Next" and then "Finish"




17) In the Data Source page go to "Custom Properties", then find the "current Schema" and change the
value to "TESTDBSCHEMA" then click "OK" and save your settings.





























Writing DAOs using Spring JDBC

Lets see how to write Daos using spring jdbc.

I create a schema TESTDBSCHEMA and in that I create a table called PERSON.

CREATE TABLE TESTDBSCHEMA.PERSON(
FIRST_NAME     CHAR(20)      NOT  NULL, 
LAST_NAME      CHAR(20)      NOT  NULL, 
AGE                     INTEGER       NOT  NULL, 
EMP_NO               INTEGER       NOT  NULL
 );
CREATE SEQUENCE TESTDBSCHEMA.PERSON_CNTR_SEQ AS INTEGER START WITH 1 INCREMENT BY 1 NO CACHE;

CREATE UNIQUE INDEX TESTDBSCHEMA.PERSON_IX ON TESTDBSCHEMA.PERSON(EMP_NO);

ALTER TABLE TESTDBSCHEMA.PERSON  ADD CONSTRAINT PERSON_IX PRIMARY KEY (EMP_NO);
We usually assign a sequence to a primary key. Here PERSON CNTR_SEQ is for entering values into EMP_NO column.

For this table we can write a Transfer Object (TO) , also called as domain class as shown below.

public class Person {
          private String firstName;
          private String lastName;
          private Integer age;
          private Integer empNo;
//setters and getters
}

JdbcTemplate Class:
This is the central class in the JDBC core package. It simplifies the use of JDBC and helps to avoid common errors. It executes core JDBC workflow, leaving application code to provide SQL and extract results. This class executes SQL queries or updates, initiating iteration over ResultSets and catching JDBC exceptions and translating them to the generic, more informative exception hierarchy defined in the org.springframework.dao package.
(Ref: http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/jdbc/core/JdbcTempla te.html)

Most of the exceptions thrown by Spring Jdbc API are runtime, so we don't have to handle those exceptions. In conventional Jdbc Daos we would have to handle all the subclasses of java.sql.SQLException which is a pain.


SimpleJdbcTemplate  Class:
This class basically evolved from JdbcTemplate class. It can take advantage of java 1.5 features like autoboxing, generics and variable-length arguments to simplify its usage.We can either instantiate the SimpleJdbcTemplate  directky or retrieve its instance by extending SimpleJdbcDaoSupport class.
(Ref: Spring Recipes 2.5 Apress Edition)

Here is the code for the dao with simple CRUD operations

public class JdbcPersonDao extends SimpleJdbcDaoSupport  implements PersonDao{

public JdbcPersonDao{)
 
public List<Person> readAll{){
       String sql = "SELECT* FROM TESTDBSCHEMA.PERSON";
       List<Person> persons= getSimpleJdbcTemplate{).query{sql,new PersonRowMapper{));
      return persons;
}

public int insert{Person person) {
         String sql = "INSERT IN TO TESTDBSCHEMA.PERSON{FIRST_NAME, LAST_NAME, AGE) " +  "VALUES{:firstName,:lastName,:age, NEXT VALUE FOR TESTDBSCHEMA.PERSON_CNTR_SEQ)";
   Map<String, 0bject> parameters = new HashMap<String,0bject>{);
   parameters.put{"firstName", person.getFirstName{));
   parameters.put{"lastName", person.getLastName{));
   parameters.put{"age", person.getAge{));
  SqlParameterSource parameterSource = new MapSqlParameterSource{parameters);
  return getSimpleJdbcTemplate{).update{sql,parameterSource);
}

public int update{Person person){
   String sql = "UPDATE TESTDBSCHEMA.PERSON  SET FIRST_NAME = :firstName,     LAST_NAME:lastName, AGE = :age" + "WHERE EMP_NO = :empNo";

   Map<String,0bject> parameters = new HashMap<String,0bject>{);
   parameters.put{"firstName", person.getFirstName{));
   parameters.put{"lastName", person.getLastName{));
   parameters.put{"age", person.getAge{));
   parameters.put{"empNo", person.getEmpNo{));

   SqlParameterSource parameterSource = new MapSqlParameterSource{parameters);
   return getSimpleJdbcTemplate{).update{sql,parameterSource);
}

public int delete{Integer empNo) {
   String sql = "DELETE FROM TESTDBSCHEMA.PERSON  WHERE EMP_NP = :empNo" ;
   Map<String,Object> parameters = new HashMap<String, 0bject>{);
   parameters.put{"empNo",empNo);
   return getSimpleJdbcTemplate{).update{sql,parameters);
}

public Person getPerson(Integer  empNo){
 String sql = "SELECT* FROM TESTDBSCHEMA.PERSON  WHERE EMP NO= :EMPnO ";         Map<String,Object> parameters = new HashMap<String,Object>(); parameters.put("empNo", empNo);
 return getSimpleJdbcTemplate().queryForObject(sql, new PersonRowMapper(),parameters);
}

}

public class PersonRowMapper ParameterizedRowMapper<Person>{
    public Person mapRow(ResultSet rs, int argl) throws SQLException{
        Person person = new Person();
        person.setAge(rs.getint("AGE"));
        person.setEmpNo(rs.getint("EMP_NO"));
        person.setFirstName(rs.getString("FIRST_NAME"));
        person.setLastName(rs.getString("LAST_NAME"));
        return person;
    }
}   

In your spring configuration you will now have these following entries.

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/TestDBDatasource" />
</bean>

<bean id="personDao" class="JdbcPersonDao">
<property name="dataSource"  ref="dataSource" />
</bean>


We can just inject dataSource to PersonDao and the inherited methods from SimpleJdbcDaoSupport would generate JdbcTemplate for us.  Or we could also create our own JdbcTemplate and inject it in to PersonDao as shown below.

<bean id="jdbcTemplate"  class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource"  ref="dataSource"/>
</bean>

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/TestDBDatasource"  />
</bean>

<bean id="personDao" class="JdbcPersonDao">
<property name="jdbcTemplate"  ref="jdbcTemplate"/>
</bean>

Now you can inject the personDao to any of your objects using spring DI.


How to write Spring Jdbc Dao  without row mapper class?


Here is the code.

public List<Person> createList(List<Map<String, Object>> rows){
     List<Person> persons= new ArrayList<Person>();
     for(Map profileMap : rows){
           persons.add(this.createOneObject(profileMap));

      }
  return persons;

public Person createOneObject(Map  personMap){
   Person person = new Person();
   person.setAge((Integer)personMap.get( "AGE"  )  )  ;                 person.setLastName(((String)personMap.get( "FISRT_NAME"  )) .trim()); 
person.setLastName(((String)personMap.get( "LAST_NAME" )) .trim());
person.setEmpNo((Integer)personMap.get("EMP_NO"));
return person;

public List<Person> readAll(){
  String sql = "SELECT* FROM TESTDBSCHEMA.PERSON";
  return this.createList(this.getSimpleJdbcTemplate().queryForList(sql));
}


public Person getPerson(Integer empNo){
  String sql = "SELECT* FROM TESTDBSCHEMA.PERSON  WHERE EMP NO= :empNo ";   Map<String,Object> parameters= new HashMap<String,Object>(); parameters.put("empNo", empNo);
return this.createOneObject(this.getSimpleJdbcTemplate().queryForMap(sql, parameters));
}
How to write Spring Jdbc Dao that has SQL IN clause?

String sql = "SELECT* FROM PERSON WHERE AGE IN (:agesList)"i
List<Integer> agesList = new ArrayList<Integer>();
agesList.add(30);
agesList.add(40);
MapSqlParameterSource parameters= new MapSqlParameterSource();
parameters.addValue("agesList", agesList);
return this.createList(this.getSimpleJdbcTemplate().queryForList(sql,parameters)


How to remove schema name before table name in sql query?

 
The examples above shows that we hard coded the schema name before the table name. In real time environments we would usually find that the schema name would be different for different environments. We wouldn't want to hard code the schema name in the code.


There are 2 ways this can be done

1. Externalize the schema name in a separate bean as shown below. The only  drawback with this solution is that you need to create different ears with different schema names for different environments with different schema names. However it does externalize the schema name from code to configuration.

<bean id="schema" class="java.lang.String">
        <constructor-arg value="TESTDBSCHEMA"/>
</bean>

<bean id="personDao" class="JdbcPersonDao">
<constructor-arg> <ref  bean="dataSource"/> </constructor-arg>
<constructor-arg> <ref  bean="schema"/> </constructor-arg>
</bean>


public JdbcPersonDao(DataSource ds, String schema){
       setDataSource(ds);
       getJdbcTemplate().execute("SET CURRENT SCHEMA   "  +  schema);
}
Schema is set in different databases in different ways. The Set schema statement above works only for db2.

2. While creating the datasource (JNDI) you can specify "currentSchema" custom property for a data source in the server (RSA or Websphere).
The description of this property in RSA is given as following "It identifies the default schema name used to qualify unqualified database object references where applicable in dynamically prepared SQL statements. Unless currentSchema is used, the default schema name is the
authorization id of the current session user." This is pretty much self explanatory.

The instructions to set this field (currentSchema) is described in this post "Creating a DataSource in RSA".

The second method is usually followed in real time environments. The first method however can be used when the development is done in tomcat or at times when a datasource jndi is not created during development phase of project.

Now we don't need to specify the schema name in the query as shown below


public Person getPerson(Integer  empNo){
String sql = "SELECT* FROM PERSON WHERE EMP_NO = :empNo ";

Map<String,Object>  parameters= new  HashMap<String,Object>();
parameters.put("empNo", empNo);
return this.createOneObject(this.getSimpleJdbcTemplate(}.queryForMap(sql, parameters)) ;

Saturday, December 10, 2011

JUNIT - java.lang.IllegalStateException: 2 matchers expected, 1 recorded.

So I've been planning to write this down for a long time, finally got sometime to do it.

If you are new to JUnit you would often find yourself facing this error .

java.lang.lllegalStateException: 2 matchers expected, 1 recorded
or
i matchers expected, j recorded.....

Here is the complete trace:

java.lang.IllegalStateException: 2 matchers expected, 1 recorded.
at
org.easymock. internal. Expected Invocation .create MissingMatchers( Expected Invocation .java :56)
at org.easymock. internal. Expected Invocation.<init>( Expected Invocation .java :48)
at org.easymock.internal.Expectedlnvocation.<init>(Expectedlnvocation.java:40)
at org.easymock.internai.RecordState.invoke(RecordState.java:76)
at org.easymock.internal.MocklnvocationHandler.invoke(MocklnvocationHandler.java:38)
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:72)
at $Proxy2 .getDataByGroupslist( Unknown Source)
at
..................................
at sun.reflect.NativeMethodAccessorlmpl.invokeO(Native Method)
at sun.reflect.NativeMethodAccessorlmpl.invoke(NativeMethodAccessorlmpl.java:4~)
at sun.reflect.DelegatingMethodAccessorlmpl.invoke(DelegatingMethodAccessorlmpl.java:25)
at java .lang. reflect. Method. invoke( Method .java :600)
at org.junit.runners.modei.FrameworkMethod$1.runReflectiveCaii(FrameworkMethod.java:44)
at org.j unit. intern a l.runners.modei.ReflectiveCa liable .run( ReflectiveCa II a ble.java: 15)
at org.j unit. runners. mode I. Fra mewo rkMethod. invoke Explosively( Framewo rkMethod .java :41)
at org.junit.internal.runners.statements.lnvokeMethod.evaluate(lnvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.runners.BiockJUnit4CiassRunner.runChild{BiockJUnit4CiassRunner.java:76)
at org.junit.runners.BiockJUnit4CiassRunner.runChild{BiockJUnit4CiassRunner.java:SO)
at org.junit.runners.ParentRunner$3.run{ParentRunner.java:193)
at org.junit. runners. Pa rentRunner$1.sched ule{Pa rentRu n ner.java :52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$OOO{ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.interna l.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390}
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

How to fix this?

The answer is that "The mock should contain all fixed values or all matchers."
EasyMock documentation (http://easymock.org/EasyMock2_2_Documentation.html) says
"If you would like to use matchers in a call, you have to specify matchers for all arguments of the method call. ."

For Example 
1.  EasyMock.expect(testTableDao.getDataByGroupslist(groups, 1)).andReturn(testTablesRows);   - works
2.  EasyMock.expect(testTableDao.getDataByGroupslist(EasyMock.isA(List.class), EasyMock.isA(Integer.class))).andReturn(testTablesRows);   - works
3.  EasyMock.expect(profileDao.getProfilesByGroupslistAndCntctCntrCode(groups,EasyMock.isA(Integer.class))).andReturn(testTableRows); -doesn't work

The code1 perfectly works fine because both the parameters for the method of the mocked object are fixed values.
The code2 perfectly works fine because both the parameters for the method of the mocked object are matchers.
The code3 would throw the java.lang.lllegaiStateException: 2 matchers expected, 1 recorded  because one parameter is a fixed value and the other is a matcher.

Saturday, December 3, 2011

Ajax call using JQuery

Here is a basic version of the method that does ajax call using jquery. This does a synchronous ajax call. Change async parameter to true to make it asynchronous.

function doAjaxCall(url, dataMap){
    var jqxhr =$.ajax({ uri: uri,
    type: "POST",
    data: dataMap,
    cache: false,
    async: false
    })
    .success( function(){})
    .error(function() {})
    .complete(function() {});
    return jqxhr;
}




var data={};
data.inputOne = 1;
data.inputTwo = "test";
url= "testUrl.do" ;

jqxhr = doAjaxCall(url, data);
jqxhr.success(function(html){
 alert("return value is: " + html);
});

jqxhr.error(function(html){
 alert("error occured: " + html);
});