Monday, April 28, 2014

SOAP: Unit Testing with Spring Integration and Spring WS

Integration Testing Support in Spring WS 2.0:
Spring WS 2.0 provides an integration test framework, which will help you test the content of the message.
It provides support for testing both client-side (written using WebServiceTemplate) and server-side (having @Endpoint annotation) code. The best part of using this framework is that you do not have to deploy on the actual server to do the integration testing. It provides a mock server (MockWebServiceServer) for the client side and a mock client (MockWebServiceClient) for the server side. Let's write the client and server-side integration test for our service.

Add spring ws test dependency:

    <!-- For Testing -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.ws</groupId>
            <artifactId>spring-ws-test</artifactId>
            <version>2.1.4.RELEASE</version>
        </dependency>

Create Client Test using MockWebServiceClient:
package com.fpt.webservices.endpoint;

import static org.springframework.ws.test.server.RequestCreators.withPayload;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/application-context-ws-TEST.xml" })
public class RoleEndPointTest {

    @Autowired
    private ApplicationContext applicationContext;

    private MockWebServiceClient mockClient;

    @Before
    public void createClient() {
        Assert.assertNotNull(applicationContext);
        mockClient = MockWebServiceClient.createClient(applicationContext);
    }

    @Test
    public void testGetRoleResponse() throws IOException {

        String request = "<ns2:RoleRequest xmlns:ns2='urn:springws:springwsservices'>"
                + "        <ns2:roleId>1</ns2:roleId>"
                + "        <ns2:roleName>roleName</ns2:roleName>"
                + "     </ns2:RoleRequest>";

        Source responsePayload = new StringSource(
                "<ns2:RoleResponse xmlns:ns2='urn:springws:springwsservices'>"
                        + "         <ns2:RoleDetails>"
                        + "            <ns2:roleId>1</ns2:roleId>"
                        + "            <ns2:roleName>roleName</ns2:roleName>"
                        + "         </ns2:RoleDetails>"
                        + "      </ns2:RoleResponse>");

        Resource schema = new FileSystemResource("src/main/resources/springws.xsd");

        mockClient.sendRequest(withPayload(new StringSource(request)))
                .andExpect(payload(responsePayload))
                .andExpect(ResponseMatchers.validPayload(schema));
    }
    
    /**
     * For validation
     * 
     * @throws IOException
     */
    @Test
    public void testGetRoleResponseInvalidPayLoad() {

        String request = "<ns2:RoleRequest xmlns:ns2='urn:springws:springwsservices'>"
                + "        <ns2:roleId>roleId</ns2:roleId>"
                + "        <ns2:roleName>roleName</ns2:roleName>"
                + "     </ns2:RoleRequest>";

        Source responsePayload = new StringSource(
                "<ns2:RoleResponse xmlns:ns2='urn:springws:springwsservices'>"
                        + "         <ns2:RoleDetails>"
                        + "            <ns2:roleName>roleName</ns2:roleName>"
                        + "         </ns2:RoleDetails>"
                        + "      </ns2:RoleResponse>");

        mockClient.sendRequest(withPayload(new StringSource(request)))
                .andExpect(payload(responsePayload));
    }
}

Create Client Test using MockWebServiceClient:

package com.fpt.webservices.common;

import java.math.BigInteger;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/application-context-ws-TEST.xml" })
public class RoleClientIntegrationTest {
    @Autowired
    private RoleClient roleClient;
    
    @Autowired
    private WebServiceTemplate webServiceTemplate;

    private MockWebServiceServer mockWebServiceServer;

    @Before
    public void createServer(){
        mockWebServiceServer = MockWebServiceServer.createServer(webServiceTemplate);
    }
    
    @Test
    public void getRoleInfo(){
        String request = "<ns2:RoleRequest xmlns:ns2='urn:springws:springwsservices'>"
                + "        <ns2:roleId>1</ns2:roleId>"
                + "        <ns2:roleName>role name</ns2:roleName>"
                + "     </ns2:RoleRequest>";

        Source responsePayload = new StringSource(
                "<ns2:RoleResponse xmlns:ns2='urn:springws:springwsservices'>"
                        + "         <ns2:RoleDetails>"
                        + "            <ns2:roleId>1</ns2:roleId>"
                        + "            <ns2:roleName>role name</ns2:roleName>"
                        + "         </ns2:RoleDetails>"
                        + "      </ns2:RoleResponse>");
        
        mockWebServiceServer.expect(RequestMatchers.payload(new StringSource(request))).andRespond(ResponseCreators.withPayload(responsePayload));
        
        Role role = roleClient.getRoleInfo();
        Assert.assertEquals(BigInteger.ONE, role.getRoleId());
    }
}


Source Code

SOAP: Spring Web Service

SOAP Web Services provide a platform agnostic integration mechanism that allows disparate systems to exchange data regardless of the platform they are running on.

For example, SOAP web services are commonly used to integrate .NET applications with applications running on the Java platform.
Almost all modern platforms and frameworks (Java, .Net, Ruby, PHP, etc) provide comprehensive libraries and tooling that allow developers to quickly and easily expose and consume SOAP services.

This post will look at Spring Web Services and take you through a step by step tutorial for building, deploying and testing a simple role first SOAP service for retrieving simple role client details.
  1. Create schema file springws.xsd:
    <?xml version="1.0" encoding="UTF-8"?>
    <!-- (c) 2010 DIRECTV, Inc. All rights reserved. -->
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        elementFormDefault="qualified" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
        xmlns:tns="urn:springws:springwsservices" targetNamespace="urn:springws:springwsservices"
        xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
        jaxb:extensionBindingPrefixes="xjc" jaxb:version="2.1">
    
        <xsd:complexType name="Role">
            <xsd:sequence>
                <xsd:element name="roleId" type="xsd:integer" />
                <xsd:element name="roleName" type="xsd:string" />
            </xsd:sequence>
        </xsd:complexType>
    
        <xsd:element name="RoleResponse">
            <xsd:complexType>
                <xsd:sequence>
                    <xsd:element name="RoleDetails" type="tns:Role" />
                </xsd:sequence>
            </xsd:complexType>
        </xsd:element>
    
        <xsd:element name="RoleRequest">
            <xsd:complexType>
                <xsd:sequence>
                    <xsd:element name="roleId" type="xsd:integer" />
                    <xsd:element name="roleName" type="xsd:string" />
                </xsd:sequence>
            </xsd:complexType>
        </xsd:element>
    
    </xsd:schema>
    
  2. Create application context application-context-ws.xml:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:oxm="http://www.springframework.org/schema/oxm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:sws="http://www.springframework.org/schema/web-services"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="    http://www.springframework.org/schema/beans                            
                                http://www.springframework.org/schema/beans/spring-beans-3.0.xsd    
                                http://www.springframework.org/schema/oxm 
                                http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd    
                                http://www.springframework.org/schema/web-services
                                http://www.springframework.org/schema/web-services/web-services-2.0.xsd                    
                                http://www.springframework.org/schema/context
                                http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    
        <!-- scans packages to find and register beans and activate annotations 
            within the application context -->
        <context:component-scan base-package="com.fpt.webservices" />
    
        <!-- enable the support for @Endpoint and related Spring-WS annotations -->
        <sws:annotation-driven />
    
        <oxm:jaxb2-marshaller id="marshaller"
            contextPath="com.fpt.webservices.model" />
    
        <bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
            <property name="marshaller" ref="marshaller" />
            <property name="unmarshaller" ref="marshaller" />
            <property name="defaultUri" value="http://localhost:8081/spring-ws-master/" />
        </bean>
    
        <!-- Our test service bean -->
        <bean id="RoleDetailService"
            class="org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition"
            lazy-init="true">
            <property name="schemaCollection">
                <list>
                    <bean
                        class="org.springframework.xml.xsd.commons.CommonsXsdSchemaCollection">
                        <property name="inline" value="true" />
                        <property name="xsds">
                            <list>
                                <value>classpath:springws.xsd</value>
                            </list>
                        </property>
                    </bean>
                    <bean
                        class="org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor">
                        <property name="validationActions" value="UsernameToken Timestamp" />
                        <property name="validationCallbackHandler">
                            <bean
                                class="org.springframework.ws.soap.security.wss4j.callback.SimplePasswordValidationCallbackHandler">
                                <property name="users">
                                    <props>
                                        <prop key="Bert">Ernie</prop>
                                    </props>
                                </property>
                            </bean>
                        </property>
                    </bean>
                </list>
            </property>
            <property name="portTypeName" value="RoleDetailService" />
            <property name="serviceName" value="RoleDetailService" />
            <property name="locationUri" value="/endpoints" />
        </bean>
    
        <!--Way 01 For validating your request and response So that you don't send 
            a string instead of an integer -->
        <bean
            class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping">
            <property name="interceptors">
                <list>
                    <ref local="validatingInterceptor" />
                </list>
            </property>
        </bean>
        <bean id="validatingInterceptor"
            class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
            <property name="schema" value="classpath:springws.xsd" />
            <property name="validateRequest" value="true" />
            <!-- <property name="validateResponse" value="true" /> -->
        </bean>
    </beans>
    
  3. Create EndPoint layer:
    package com.fpt.webservices.endpoint;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.ws.server.endpoint.annotation.Endpoint;
    import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
    import org.springframework.ws.server.endpoint.annotation.RequestPayload;
    import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
    
    import com.fpt.webservices.model.Role;
    import com.fpt.webservices.model.RoleRequest;
    import com.fpt.webservices.model.RoleResponse;
    import com.fpt.webservices.service.RoleService;
    
    @Endpoint
    public class RoleEndPoint {
    
        private static final String TARGET_NAMESPACE = "urn:springws:springwsservices";
        
        @Autowired
        private RoleService roleService;
        
        //http://localhost:8080/spring-ws-master/webservices/RoleDetailService.wsdl
        @PayloadRoot(localPart = "RoleRequest", namespace = TARGET_NAMESPACE)    
        public @ResponsePayload
        RoleResponse getRoleResponse(@RequestPayload RoleRequest roleRequest) {
            RoleResponse roleResponse = new RoleResponse();
            roleResponse = roleService.getRole(new Role(roleRequest.getRoleId(), roleRequest.getRoleName()));
            return roleResponse;
        }
    }
    
  4. Create Service layer:
    package com.fpt.webservices.service;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import com.fpt.webservices.dao.RoleDao;
    import com.fpt.webservices.model.Role;
    import com.fpt.webservices.model.RoleResponse;
    
    @Service
    public class RoleServiceImpl implements RoleService {
    
        @Autowired
        private RoleDao roleDao;
        
        @Override
        public RoleResponse getRole(Role role) {
            return roleDao.getRole(role);
        }
    }
    
  5. Create Dao layer:
    package com.fpt.webservices.service;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import com.fpt.webservices.dao.RoleDao;
    import com.fpt.webservices.model.Role;
    import com.fpt.webservices.model.RoleResponse;
    
    @Service
    public class RoleServiceImpl implements RoleService {
    
        @Autowired
        private RoleDao roleDao;
        
        @Override
        public RoleResponse getRole(Role role) {
            return roleDao.getRole(role);
        }
    }
    
    
    
    Source Code

Thursday, March 13, 2014

JARX-RS: JerseyTest For Post PayLoad

Hi all,
Today, i have new a post How to write Unit Test for method GET() and POST() using JARX-RS technical.
Especially, POST one PayLoad with JSON type and validate this PayLoad is correct or incorrect.
NOTE: you have to extend JerseyTest

package com.sample.common.endpoint;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.log4j.Logger;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.request.RequestContextListener;
import com.sample.common.domain.Error;
import com.sample.common.domain.Users;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.spi.spring.container.servlet.SpringServlet;
import com.sun.jersey.test.framework.JerseyTest;
import com.sun.jersey.test.framework.WebAppDescriptor;

public class UserEndPointTest extends JerseyTest {
    private final Logger log = Logger.getLogger(this.getClass());

    public UserEndPointTest() throws Exception {
        super(
                new WebAppDescriptor.Builder(
                        "com.sun.jersey.samples.springannotations.resources.jerseymanaged")
                        .contextPath("spring-jersey-validation-payload")
                        .contextParam("contextConfigLocation",
                                "classpath:applicationContext_TEST.xml")
                        .servletClass(SpringServlet.class)
                        .contextListenerClass(ContextLoaderListener.class)
                        .requestListenerClass(RequestContextListener.class)
                        .initParam("com.sun.jersey.config.feature.Trace",
                                "true")
                        .initParam("jersey.config.server.provider.classnames",
                                "org.glassfish.jersey.filter.LoggingFilter")
                        .initParam(
                                "com.sun.jersey.spi.container.ContainerRequestFilters",
                                "com.sun.jersey.api.container.filter.LoggingFilter")
                        .initParam(
                                "com.sun.jersey.spi.container.ContainerResponseFilters",
                                "com.sun.jersey.api.container.filter.LoggingFilter")
                        .initParam("com.sun.jersey.config.property.packages",
                                " com.fasterxml.jackson.jaxrs.json")
                        .initParam(
                                "com.sun.jersey.api.json.POJOMappingFeature",
                                "true").build());

        log.debug("In UserEndPointTest constructor.");
    }

    @Test
    public void testGetUserJSON() throws Exception {
        WebResource webResource = resource();
        ClientResponse returnJSON = webResource.path("service")
                .type(MediaType.APPLICATION_JSON).get(ClientResponse.class);
        Users users = returnJSON.getEntity(Users.class);
        Assert.assertEquals(2, users.getUser().size());
    }

    @Test
    public void testGetUserXML() throws Exception {
        WebResource webResource = resource();
        ClientResponse returnXML = webResource.path("service")
                .type(MediaType.APPLICATION_XML).get(ClientResponse.class);
        Users users = returnXML.getEntity(Users.class);
        Assert.assertEquals(2, users.getUser().size());
    }

    @Test
    public void testAddUserJSONSuccess() throws Exception {
        WebResource webResource = resource();

        String jsonPayload = "{\"user\":[{\"userId\":\"userid1\",\"birthDate\":1393405118626}]}";

        ClientResponse returnJSON = webResource.path("service")
                .type(MediaType.APPLICATION_JSON)
                .post(ClientResponse.class, jsonPayload);

        Assert.assertEquals(Response.Status.OK.getStatusCode(),
                returnJSON.getStatus());
    }

    @Test
    public void testAddUserJSONAHalf() throws Exception {
        WebResource webResource = resource();

        String jsonPayload = "{\"user\":[{\"userId\":\"userid1\",\"birthDate\":1393409642708},{\"userId\":null,\"birthDate\":null}]}";

        ClientResponse returnJSON = webResource.path("service")
                .type(MediaType.APPLICATION_JSON)
                .post(ClientResponse.class, jsonPayload);

        com.sample.common.domain.Error error = returnJSON
                .getEntity(Error.class);

        Assert.assertEquals("Add one user Fail", 1, error.getFailureCount());
        Assert.assertEquals("Add one user Success", 1, error.getSuccessCount());
        Assert.assertEquals("Add a half user", error.getMessage());
    }

    @Test
    public void testAddUserJSONFailCompletely() throws Exception {
        WebResource webResource = resource();

        String jsonPayload = "{\"user\":[{\"userId\":null,\"birthDate\":null}]}";

        ClientResponse returnJSON = webResource.path("service")
                .type(MediaType.APPLICATION_JSON)
                .post(ClientResponse.class, jsonPayload);

        com.sample.common.domain.Error error = returnJSON
                .getEntity(Error.class);

        Assert.assertEquals("Add one user Fail", 1, error.getFailureCount());
        Assert.assertEquals("Add User Failure Completely", error.getMessage());
    }
}

Source Code

Wednesday, February 26, 2014

Spring JARX-RS: How to validate PayLoad [ PayLoadValidator ]

Hi all,
- Today, i have a new post . How to validate an object with annotations @NotNull, @Valid, any validations annotations.
- This post will help you understand using spring jersey + validation annotations.

Create Class PayLoadValidator:

package com.sample.common.util;

import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.annotation.PostConstruct;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.ValidatorFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.sample.common.domain.User;
/**
 *
 * validate object has annotation @Valid@NotNull

 *
 * @author HieuNT29
 *
 */

@Component
public class PayloadValidator {
    private javax.validation.Validator validator = null;
    private static final Logger LOGGER = LoggerFactory
            .getLogger(PayloadValidator.class);

    PayloadValidator() {
    };

    @PostConstruct
    public void setup() {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        validator = factory.getValidator();
    }
    @SuppressWarnings("unchecked")

    public Error validate(List< ? extends User> requestEntries, Error errorResponse) {
        Iterator vIterator = (Iterator) requestEntries.iterator();
        int failureCount = 0;
        while (vIterator.hasNext()) {
            User userReqEntry = vIterator.next();
            Set errorSet = validator.validate(userReqEntry);
            if (errorSet.size() > 0) {
                StringBuffer errorMessage = new StringBuffer();
                for (ConstraintViolation error : errorSet) {
                    System.out.println(error);
                }  
                LOGGER.debug("Error message {}", errorMessage.toString());
                vIterator.remove();
                errorResponse.setFailureCount(++failureCount);
            }
        }
        return errorResponse;
    }
}


Source Code

Thursday, December 19, 2013

Spring MVC: Apply Mockito Framework at Controller.

Hi !!! Today, i have a new post. How to apply Mockito Framework for Spring MVC at Controller layer.

What is Mockito?
Mockito is a mocking framework that tastes really good. It lets you write beautiful tests with clean & simple API. Mockito doesn't give you hangover because the tests are very readable and they produce clean verification errors: Read more https://code.google.com/p/mockito/

I) Add Mockito Maven Dependency:         
II) Controller Layer:
package com.fpt.controller;
import java.util.List;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.fpt.domain.Person;
import com.fpt.service.PersonService;

@Controller
public class RestController {
    protected static Logger logger = Logger.getLogger(RestController.class);

    @Autowired
    private PersonService personService;

    // http://localhost:8080/spring-mvc-mokito/mvc/all/persons

    @RequestMapping(value = "/all/persons", method = RequestMethod.GET, headers = "Accept=application/xml, application/json")

    public String getAllPerson(ModelMap model) {
        logger.debug("Provider has received request to get all persons");
        List result = personService.getAllPerson();
        model.addAttribute("model_get_all_person", result);
        return "get_all_person";
    }
}

III) Unit test for Controller layer applying Mockito:
package com.fpt.controller.test;

import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import java.util.ArrayList;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import com.fpt.controller.RestController;
import com.fpt.domain.Person;
import com.fpt.service.PersonService;


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
public class RestControllerAnnoTest {

    @Configuration
    static class ContextConfiguration {

        @Bean
        public PersonService personService() {
            return Mockito.mock(PersonService.class);
        }

        @Bean
        public RestController loginController() {
            return new RestController();
        }
    }

    @Autowired
    private RestController restController;

    @Autowired
    private PersonService personService;

    private MockMvc mockMvc;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        mockMvc = MockMvcBuilders.standaloneSetup(this.restController).build();
    }

    @After
    public void teardown() {
        mockMvc = null;
    }

    @Test
    public void testGetAllPerson() throws Exception {
        Person p1 = new Person();
        p1.setFirstName("firstName01");
        p1.setLastName("lastName01");
        p1.setId(123l);
        p1.setMoney(321d);

        Person p2 = new Person();
        p2.setFirstName("firstName02");
        p2.setLastName("lastName02");
        p2.setId(123l);
        p2.setMoney(321d);

        List expectedPeople = new ArrayList();
        expectedPeople.add(p1);
        expectedPeople.add(p2);

        when(personService.getAllPerson()).thenReturn(expectedPeople);

        this.mockMvc
                .perform(get("/all/persons"))
                .andExpect(status().isOk())
                .andExpect(
                        model().attribute("model_get_all_person",
                                expectedPeople))
                .andExpect(view().name("get_all_person"));
        ;
    }
}

IV) Create a new file ApplicationContent_Test.xml at src/test/resources:
 
V) Unit test for Controller layer without Mockito:
package com.fpt.controller.test;

import static org.junit.Assert.assertEquals;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.ui.ModelMap;
import com.fpt.controller.RestController;
import com.fpt.domain.Person;
import com.fpt.service.PersonService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/applicationContext_TEST.xml" })
public class RestControllerXmlTest {

    @Autowired
    private RestController restController;

    @Autowired
    private PersonService personService;

    @Test
    public void testGetAllPerson() throws Exception {
        Person p1 = new Person();
        p1.setFirstName("firstName01");
        p1.setLastName("lastName01");
        p1.setId(123l);
        p1.setMoney(321d);

        Person p2 = new Person();
        p2.setFirstName("firstName02");
        p2.setLastName("lastName02");
        p2.setId(123l);
        p2.setMoney(321d);

        List expectedPeople = personService.getAllPerson();
        expectedPeople.add(p1);
        expectedPeople.add(p2);

        ModelMap modelMap = new ModelMap();
        String viewName = restController.getAllPerson(modelMap);
        assertEquals("get_all_person", viewName);

        @SuppressWarnings("unchecked")
        List listPersons = (List) modelMap             .get("model_get_all_person");


        assertEquals("There are 2 objects",2, listPersons.size());     
        assertEquals("firstName01", listPersons.get(0).getFirstName());
        assertEquals(Long.valueOf(123), listPersons.get(0).getId());
        assertEquals("lastName01", listPersons.get(0).getLastName());
        assertEquals(Double.valueOf(321.0), listPersons.get(0).getMoney());
    }
}

Source Code

Thursday, November 21, 2013

Spring AOP + AspectJ: Before and After

Spring AOP (Aspect-oriented programming) framework is used to modularize cross-cutting concerns in aspects. Put it simple, it’s just an interceptor to intercept some processes, for example, when a method is execute, Spring AOP can hijack the executing method, and add extra functionality before or after the method execution.
In Spring AOP, 4 type of advices are supported :
  • Before advice – Run before the method execution
  • After returning advice – Run after the method returns a result
  • After throwing advice – Run after the method throws an exception
  • Around advice – Run around the method execution, combine all three advices above.

Spring AOP Advices

package com.fpt.aop.pointcut;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class SearchEngineeAfterPointcut{
    private static final org.slf4j.Logger LOGGER = LoggerFactory
            .getLogger(SearchEngineeAfterPointcut.class);


    /**
     * Define pointcut inline for any of the advices
     * 

     * http://www.tutorialspoint.com/spring/aspectj_based_aop_appoach.htm
     * 

     * @param joinPoint
     * @throws Throwable
     */

    @After("within(com.fpt.controller..*) && execution(* *(..,@org.springframework.web.bind.annotation.PathVariable (*),..))")
    public void checkAfterPointCut(JoinPoint joinPoint) throws Throwable {
        // get method arguments

        Object[] args = joinPoint.getArgs();
        for (int i = 0; i < args.length; i++) {
            LOGGER.debug("AFTER: checkAfterPointCut:{}",i);
        }
    }
}


package com.fpt.aop.pointcut;


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class SearchEngineeBeforePointcut{

    private static final org.slf4j.Logger LOGGER = LoggerFactory
            .getLogger(SearchEngineeBeforePointcut.class);

    /**
     * Define pointcut inline for any of the advices
     * 

     * http://www.tutorialspoint.com/spring/aspectj_based_aop_appoach.htm
     * 

     * @param joinPoint
     * @throws Throwable
     */


    @Before("within(com.fpt.controller..*) && execution(* *(..,@org.springframework.web.bind.annotation.PathVariable (*),..))")
    public void checkBeforePointCut(JoinPoint joinPoint) throws Throwable {    

        // get method arguments

        Object[] args = joinPoint.getArgs();
        for (int i = 0; i < args.length; i++) {
            LOGGER.debug("BEFORE: checkBeforePointCut:{}",i);
        }
    }
}


Spring MVC

package com.fpt.controller;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.fpt.domain.Person;
import com.fpt.domain.PersonList;
import com.fpt.service.PersonService;

@Controller
public class RestController {
    protected static Logger logger = Logger.getLogger(RestController.class);

    @Autowired
    private PersonService personService;

    // http://localhost:8080/spring-aop-search/mvc/persons

    @RequestMapping(value = "/persons", method = RequestMethod.GET, headers = "Accept=application/xml, application/json")
    public @ResponseBody
    PersonList getPerson() {
        logger.debug("Provider has received request to get all persons");
        PersonList result = new PersonList();
        result.setData(personService.getAllPerson());
        return result;
    }

    // http://localhost:8080/spring-aop-search/mvc/person/1

    @RequestMapping(value = "/person/{id}", method = RequestMethod.GET, headers = "Accept=application/xml, application/json")
    public @ResponseBody
    Person getPerson(@PathVariable("id") Long id) {
        logger.debug("Provider has received request to get person with id: "
                + id);
        return personService.getPerson(id);
    }

    // http://localhost:8080/spring-aop-search/mvc/person

    @RequestMapping(value = "/person", method = RequestMethod.POST, headers = "Accept=application/xml, application/jsonp")
    public @ResponseBody
    Person addPerson(@RequestBody Person person) {
        logger.debug("Provider has received request to add new person");
        if (person.getFirstName() == null)
            throw new NullPointerException("First Name can not be null");
        return personService.addPerson(person);
    }
}


Source Code

Friday, October 25, 2013

Coupling and Cohesion

What is Coupling ?
- Coupling indicates the degree of dependence among components. Higher coupling tends to indicate poor design of classes, since it makes modifying parts of the system difficult, as modifying a component affects all the components to which the component is connected.
- Class A has behaviourA and propertiesA, and Class B has behaviourB and propertiesB. Class A uses the properties and behaviours in Class B, and Class B also uses the properties and behaviours in Class A.
- We call High Coupling (Tighly Coupling)

What is the solution ?
- Lower Coupling is better .

Problem: Sample code High Coupling
package com.scjp6.oop.coupling;
public class CalculateTaxes {
    float rate;
    float doIndia() {
    TaxRatesInIndia str = new TaxRatesInIndia();
    return rate = str.salesRate; // ouch again
    }
}

package com.scjp6.oop.coupling;

public class TaxRatesInIndia {
    public float salesRate; // should be private

    public float adjustedSalesRate; // should be private
    public float getSalesTaxRates() {
        adjustedSalesRate = new CalculateTaxes().doIndia();
        return adjustedSalesRate;
    }
}
package com.scjp6.oop.coupling;


public class LowCoupling {


    public static void main(String[] args) {
    // TODO Auto-generated method stub

    Calculate calculate = new CalculateTaxeRateIndiaImpl();
    System.out.println(calculate.doIndia());
    System.out.println(calculate.getSalesTaxRates());
    }
}
Solution: Sample code Low/ Tigh Coupling

package com.scjp6.oop.coupling;

public interface Calculate {
    float doIndia();
    float getSalesTaxRates();   
}


package com.scjp6.oop.coupling;
public class CalculateTaxeRateIndiaImpl implements Calculate {
    @Override
    public float doIndia() {
       return 0;
    }


    @Override
    public float getSalesTaxRates() {
      return 0;
    }
}


package com.scjp6.oop.coupling;

public class LowCoupling {

    public static void main(String[] args) {
     Calculate calculate = new CalculateTaxeRateIndiaImpl();
     System.out.println(calculate.doIndia());
     System.out.println(calculate.getSalesTaxRates());
    }
}


What is Cohesion
- Cohesion is the extent to which methods in a class are related. It means, a class has many methods are related.
- We can call Low Cohesion

What is the solution ?
- High Cohesion is better .

Problem: Sample code Low Cohesion
package com.scjp6.oop.cohesion;

public class ReportGrade {
    Student getStudent() {
      return new Student();
    }

    Subject getSubject() {
      return new Subject();
    } 

    Grade getGrade(){
      return new Grade();
    }
}

package com.scjp6.oop.cohesion;

public class RunLowerCohesion {

    public static void main(String[] args) {
      ReportGrade reportGrade = new ReportGrade();
      reportGrade.getGrade();
      reportGrade.getStudent();
      reportGrade.getSubject();
    }
}

Solution: Sample code High Cohesion

public class Grade {
    String studentID;
    String subjectID;
    float grade01;
    float grade02;
}

package com.scjp6.oop.cohesion;
public class Student {
    String studentID;
    String name;
    int age;
}


package com.scjp6.oop.cohesion;
public class Subject {
    String subjectID;
    String subjectName;
}


package com.scjp6.oop.cohesion;
public class ReportGradeHighCohesion {   
     Grade getGrade(){
       return new Grade();
    }
}


package com.scjp6.oop.cohesion;
public class ReportStudentHighCohesion {
    Student getStudent() {
      return new Student();
    }   
}


package com.scjp6.oop.cohesion;
public class ReportSubjectHighCohesion {
    Subject getSubject() {
      return new Subject();
    }
}


package com.scjp6.oop.cohesion;
public class RunHighCohesion {


    public static void main(String[] args) {
    ReportGradeHighCohesion reportGradeHighCohesion = new ReportGradeHighCohesion();
    reportGradeHighCohesion.getGrade();

    ReportStudentHighCohesion reportStudentHighCohesion = new ReportStudentHighCohesion();
    reportStudentHighCohesion.getStudent();

    ReportSubjectHighCohesion reportSubjectHighCohesion = new ReportSubjectHighCohesion();
    reportSubjectHighCohesion.getSubject();
    }
}