Thursday, July 18, 2013

How to explain what Java is?

Some time ago, someone asked me how I would explain someone else what Java is, "...imagine that person is someone who has little experience with Java (hence a Junior), or someone who comes from a .NET project, or a manager" he said. I thought that I should provide a high level explanation, simple and easy to understand but should provide enough detail too.

Java is a general purpose language, object oriented, and semi-interpreted that runs on a Virtual Machine. The syntax is similar to C.

Why general purpose language? Because it is suitable for different domains. This means that you can create from web applications to video games
Why semi-interpreted? Because the .java code you write has to be compiled in .class files, and these .class files run in the Virtual Machine

I would then add that Java is really a set of specifications of how the language has to be rather than a language. Different companies such as IBM or Oracle take those specifications and create their own Java implementations (aka Virtual Machines) and make them available on different operating systems.

Where does Java stand in relation to other market technologies?


Java .NET PHP SAP
Platform multiplatform only works in microsoft environment multiplatform multiplatform
Community a lot not much not much not much
Cost free license free license
Startup not immediate, choice of frameworks first immediate immediate immediate, implementation times very high
Support no yes no yes
Open Source yes no yes no
Human Resources a lot not much a lot not much

Remember this is just a high level approach into understanding what Java is from a global point of view.

Given this, is Java the best language? Is it better than, e.g. .NET? As a consultant, my answer is that it depends on the problem you want to solve; One technology may be more suitable to solve a problem, but not to solve another one, in which case, other technology may be more appropiate. But, in any case, it would require another whole post to make an analysis of what to take into account to choose a language.

Wednesday, June 12, 2013

GoF patterns: Template Method

Definition: This pattern defines the skeleton of an algorithm and let subclasses define some steps of it without changing the original algorithm structure.


Say for example, I have a service for buying tickets and I want the service to provide discounts depending on the age of the person. I want to have 2 kind of discounts, but I am sure there will be a lot more in the future. Instead of having an IF statement to do get the final price of the ticket depending on the age (and have a whole bunch of nested IF statements in the future), the ticket buying process will have the skeleton of the buying process and the step to get the final price of the ticket will be delegated to different classes. As we said, today we just have 2 different calcs of the discount but tomorrow we may have a lot more:



TicketServiceAbstract
public abstract class TicketServiceAbstract {
 
 public double buyTicket(Client client) {
  double generalTicketPrice = 50;
  double realTicketPrice = this.calculateDiscount(generalTicketPrice);
  return realTicketPrice;
 }

 protected abstract double calculateDiscount(double generalTicketPrice);

}

HighDiscountTicketService
public class HighDiscountTicketService extends TicketServiceAbstract {

 @Override
 protected double calculateDiscount(double generalTicketPrice) {
  return generalTicketPrice - 30;
 }

}

LowDiscountTicketService
public class LowDiscountTicketService extends TicketServiceAbstract {

 @Override
 protected double calculateDiscount(double generalTicketPrice) {
  return generalTicketPrice - 10;
 }

}

And this is an invocation example:

TemplateMethodPatternTest
public class TemplateMethodPatternTest {
 
 @Test
 public void templateMethodKidPatternTest() {
  
  //A new Client is created
  Client kid = new Client();
  kid.setAge(16);
  
  HighDiscountTicketService discountService = new HighDiscountTicketService();
  
  double ticketPriceForKid = discountService.buyTicket(kid);
  Assert.assertTrue(ticketPriceForKid == 20);
 }
 
 @Test
 public void templateMethodAdultPatternTest() {
  
  //A new Client is created
  Client kid = new Client();
  kid.setAge(25);
  
  LowDiscountTicketService discountService = new LowDiscountTicketService();
  
  double ticketPriceForKid = discountService.buyTicket(kid);
  Assert.assertTrue(ticketPriceForKid == 40);
 }
 
}

The Template Method pattern is similar to the Strategy pattern, in this post you can see this same example implemented with the Strategy pattern. The main difference between both patterns is that the Strategy changes its behaviour at runtime, while the Template Method changes its behaviour at compile time.

Monday, June 3, 2013

GoF patterns: Strategy

Definition: This pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable at runtime. This pattern is used when you have some logic and you want it to vary independently of the client who uses it while still having an extensible model.



Why encapsulated? Because each algorithm exists in a different class and access all that logic with a method. Why Interchangeable? Because each of those classes implement the same interface.

Say for example, I have a service for buying tickets and I want the service to provide discounts depending on the age of the person. I want to have 2 kind of discounts, but I am sure there will be a lot more in the future. Instead of having an IF statement (and have a whole bunch of nested IF statements in the future), in the whole process of buying a ticket, the strategy will be implemented in the calculus of the discount. Why? Because the result of the calculus is the same (a new price on the ticket) but the way it works is different from each other. As we said, today we just have 2 different calcs of the discount but tomorrow we may have a lot more:



TicketService
public class TicketService {
 
 private DiscountStrategy discountProcess;
 
 public double buyTicket(Client client) {
  double generalTicketPrice = 50;
  double realTicketPrice = discountProcess.calculateDiscount(generalTicketPrice);
  return realTicketPrice;
 }

}

These are the different strategies we have:

HighDiscountStrategy
public class HighDiscountStrategy implements DiscountStrategy {

 @Override
 public double calculateDiscount(double ticketPrice) {
  return ticketPrice - 30;
 }

}

LowDiscountStrategy
public class LowDiscountStrategy implements DiscountStrategy {

 @Override
 public double calculateDiscount(double ticketPrice) {
  return ticketPrice - 10;
 }

}

As you can see, our buyTicket method doesn't care about which type of discount it is applying.

Now, the question is, when do we set the type of discount? Maybe in the service constructor?
But, what if we just want one service class to be instantiated and use that same instance with every client that arrives? Well, that really depends on the problem to be solved, the Strategy pattern doesn't tell you when and how to set the discount type... In this case, I chose to create a new service for each client. So, passing the client in the constructor is enough.

So, our class will be like this with the constructor:

TicketService
public class TicketService {
 
 private DiscountStrategy discountProcess;
 
 public TicketService(Client client) {
  if (client.getAge() >= 18) {
   discountProcess = new LowDiscountStrategy();
  } else {
   discountProcess = new HighDiscountStrategy();
  }
 }
 
 public double buyTicket(Client client) {
  double generalTicketPrice = 50;
  double realTicketPrice = discountProcess.calculateDiscount(generalTicketPrice);
  return realTicketPrice;
 }

}

And an invocation example:

//A new Client is created
  Client kid = new Client();
  kid.setAge(16);
  
  //The service to create discounts is created and its behaviour changes according to the
  //age of the client
  TicketService discountService = new TicketService(kid);
  
  double ticketPriceForKid = discountService.buyTicket(kid);
  Assert.assertTrue(ticketPriceForKid == 20);
  
  //A new Client is created
  Client adult = new Client();
  adult.setAge(25);
  
  //The service to create discounts is created and its behaviour changes according to the
  //age of the client
  TicketService discountService = new TicketService(adult);
  
  double ticketPriceForAdult = discountService.buyTicket(adult);
  Assert.assertTrue(ticketPriceForAdult == 40);

Tuesday, May 28, 2013

Restful Generic DAO with Spring 3 + JPA + unit testing + integration testing

This time, we will create a generic DAO layer, a Service layer and a REST layer which exposes the Service layer to whoever wants to consume it. Unit tests and Integration tests will be created too. Everything is implemented with Spring 3.

Versions used:
  1. Spring 3.2.2.RELEASE
  2. JAXB
  3. Hibernate 4.2.1.Final
  4. Maven 3

pom.xml
<dependencies>

  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-webmvc</artifactId>
   <version>3.2.2.RELEASE</version>
  </dependency>
  
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-orm</artifactId>
   <version>3.2.2.RELEASE</version>
  </dependency>

  <dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-entitymanager</artifactId>
   <version>4.2.1.Final</version>
  </dependency>

  <dependency>
   <groupId>hsqldb</groupId>
   <artifactId>hsqldb</artifactId>
   <version>1.8.0.10</version>
  </dependency>

  <dependency>
   <groupId>log4j</groupId>
   <artifactId>log4j</artifactId>
   <version>1.2.17</version>
  </dependency>

  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>4.11</version>
   <scope>test</scope>
  </dependency>
  
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-test</artifactId>
   <version>3.2.2.RELEASE</version>
   <scope>test</scope>
  </dependency>

  <dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>servlet-api</artifactId>
   <version>2.5</version>
   <scope>test</scope>
  </dependency>

 </dependencies>

hsqldb will be our in-memory database. Let´s see the rest of the relevant pom info.

<!-- Jetty plugin -->
 <plugin>
  <groupId>org.mortbay.jetty</groupId>
  <artifactId>maven-jetty-plugin</artifactId>
  <version>6.1.10</version>
  <configuration>
   <scanIntervalSeconds>10</scanIntervalSeconds>
  </configuration>
 </plugin>
With the Maven Jetty Plugin you can manually run mvn jetty:run in your terminal and the server will be started. Now that the server is up, it lets you run the REST services tests (those tests are considered integration tests). Below you can find the automated way to treat integration tests just like normal unit tests are treated.

<!-- This one is to run integration tests -->
 <!-- By default runs all *IT.java tests -->
 <plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-failsafe-plugin</artifactId>
  <version>2.12</version>
  <executions>
   <execution>
    <goals>
     <goal>integration-test</goal>
     <goal>verify</goal>
    </goals>
   </execution>
  </executions>
 </plugin>
Similar to running mvn test to run the unit tests, when you run mvn verify, integration tests are executed. But what if you want to run unit tests and integration tests when you compile your project? Should you run mvn test verify in that case? Well, you must tell maven to start the jetty server right after unit tests finish but before integration tests run (no, you cannot use mvn test jetty:run verify)... see below:

<!-- Responsible for starting jetty before integration tests -->
 <plugin>
  <groupId>org.codehaus.cargo</groupId>
  <artifactId>cargo-maven2-plugin</artifactId>
  <version>1.2.0</version>
  <configuration>
   <container>
    <containerId>jetty6x</containerId>
    <type>embedded</type>
   </container>
  </configuration>
   <executions>
    <execution>
     <id>start-jetty</id>
     <phase>pre-integration-test</phase>
     <goals>
     <goal>start</goal>
     </goals>
    </execution>
    <execution>
     <id>stop-jetty</id>
     <phase>post-integration-test</phase>
     <goals>
     <goal>stop</goal>
     </goals>
   </execution>
  </executions>
 </plugin>
Pretty straightforward, right? Thanks to the Cargo plugin, whenever integration tests are executed, in the pre-integration-test maven phase the jetty server will be automatically started.

web.xml
<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>classpath*:spring-beans.xml</param-value>
 </context-param>

 <context-param>
  <param-name>log4jConfigLocation</param-name>
  <param-value>classpath*:log4j.properties</param-value>
 </context-param>
 <servlet>
  <servlet-name>applicationContext</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
  <servlet-name>applicationContext</servlet-name>
  <url-pattern>/client-crud/*</url-pattern>
 </servlet-mapping>
 <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>
That's a normal Spring setup.

applicationContext-servlet.xml
<!-- Enabling Spring beans auto-discovery -->
<context:component-scan base-package="ar.com.pabloExample" />
<!-- Enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="txManager" />
<!-- Enabling Spring MVC configuration through annotations -->
<mvc:annotation-driven />
In that XML we configure our beans to be scanned because we will use annotations. The transaction manager is enabled to work with annotations too.

GenericDao
public interface GenericDao<T extends Serializable> {
 
 public long count();
 public T create(T t);
 public void delete(Object id);
 public T find(Object id);
 public List<T> getAll();
 public T update(T t); 
}
That's a generic DAO interface.

ClientDao
public interface ClientDao extends GenericDao<Client> {

}
For every entity we want to use the generic DAO, we must create the interface for that entity because the generic DAO is GenericDao<?> and we must tell it which is the entity it will accept, in this case GenericDao<Client>

GenericDaoImpl
public abstract class GenericDaoImpl<T extends Serializable> implements GenericDao<T> {
 
 private Class<T> type;
 
 @SuppressWarnings("unchecked")
 public GenericDaoImpl() {
  Type t = getClass().getGenericSuperclass();
  ParameterizedType pt = (ParameterizedType) t;
  type = (Class<T>) pt.getActualTypeArguments()[0];
 }
 
 @PersistenceContext
 protected EntityManager em;

 @Override
 public long count() {
  String entity = type.getSimpleName();
  final StringBuffer queryString = new StringBuffer("select count(ent) from " + entity + " ent");
  final Query query = this.em.createQuery(queryString.toString());
  return (Long) query.getSingleResult();
 }

 @Override
 public T create(final T t) {
  em.persist(t);
  return t;
 }

 @Override
 public void delete(final Object id) {
  em.remove(em.getReference(type, id));
 }

 @Override
 public T find(final Object id) {
  return em.find(type, id);
 }

 @Override
 public T update(final T t) {
  return em.merge(t);
 }

 @SuppressWarnings("unchecked")
 @Override
 public List<T> getAll() {
  Query query = em.createQuery("from " + type.getName());
  return query.getResultList();
 }
}
This is the implementation of the generic DAO with Hibernate.

ClientDaoImpl
@Repository
public class ClientDaoImpl extends GenericDaoImpl<Client> implements ClientDao {

}
Similar to what we did with the ClientDao interface, we have to do it with the implementation too. We must create the ClientDao implementation and make it extend the generic Dao implementation.
The @Repository annotation only tells Spring this is a bean the "annotations way" of type "DAO" (see the end of the post to understand more of it).

ClientService
public interface ClientService {
 
 public Client create(Client client);
 public void delete(Integer id);
 public Client update(Client client);
 public Client find(Integer id);
 public List<Client> getAll();
 public Long count();
}
This is the  Service layer. It can be generic too, altough in this example only the DAO layer is generic.

ClientServiceImpl
@Service
public class ClientServiceImpl implements ClientService {
 
 @Autowired
 private ClientDao clientDao;

 @Override
 @Transactional(readOnly = false)
 public Client create(Client client) {
  return clientDao.create(client);
 }

 @Override
 @Transactional(readOnly = true)
 public List<Client> getAll() {
  return clientDao.getAll();
 }

 @Override
 @Transactional(readOnly = false)
 public void delete(Integer id) {
  clientDao.delete(id);
 }

 @Override
 @Transactional(readOnly = false)
 public Client update(Client client) {
  return clientDao.update(client);
 }

 @Override
 @Transactional(readOnly = false)
 public Client find(Integer id) {
  return clientDao.find(id);
 }

 @Override
 @Transactional(readOnly = true)
 public Long count() {
  return clientDao.count();
 }

}
In this class, all of our methods are transactional, that's why we annotate them with @Transactional. With @Autorwired we inject the Client DAO implementation. The @Service does the same as @Repository; It tells Spring that this class is a bean too (check the end of the post for more information about it).

spring-beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

 <!-- Datasource configured in spring and not in persitence.xml -->
 <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <property name="driverClassName" value="org.hsqldb.jdbcDriver" />
  <property name="url" value="jdbc:hsqldb:mem:testdb" />
  <property name="username" value="sa" />
  <property name="password" value="" />
 </bean>
 
 <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  <property name="persistenceXmlLocation" value="classpath:persistence.xml"/>
  <property name="persistenceUnitName" value="spring-webapp-persistenceUnit" />
  <property name="dataSource" ref="dataSource"/>
 </bean>

 <bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
  <property name="entityManagerFactory" ref="entityManagerFactory"/>
  <property name="dataSource" ref="dataSource" />
 </bean>

</beans>
This file is a normal one, we define the datasource, the hibernate entity manager and the transaction manager associated with both.

ClientRestService
@Controller
@RequestMapping("/rest-services/clients")
public class ClientRestService {
 
 private static final Logger LOGGER = Logger.getLogger(ClientService.class);
 
 @Autowired
 private ClientService clientService;

 @RequestMapping(method = RequestMethod.GET)
 @ResponseBody
 public Clients loadClients() {
  
  Clients clientsWrapper = new Clients();
  clientsWrapper.setClients(clientService.getAll());
  
  LOGGER.info("--- Client list retrieved ---");
  return clientsWrapper;
 }
 
 @RequestMapping(method = RequestMethod.POST)
 @ResponseBody
 public Client addClient(@RequestBody Client client) {
  
  Client newClient = clientService.create(client);
  
  LOGGER.info("--- New client saved ---");
  return newClient;
 }
 
 @RequestMapping(value = "/{clientId}", method = RequestMethod.PUT)
 @ResponseBody
 public Client updateClient(@PathVariable(value = "clientId") Integer clientId, @RequestBody Client client) {
  
  Client newClient = clientService.update(client);
  
  LOGGER.info("--- Client updated ---");
  return newClient;
 }
 
 @RequestMapping(value = "/{clientId}", method = RequestMethod.GET)
 @ResponseBody
 public Client findClient(@PathVariable(value = "clientId") Integer clientId) {
  
  Client foundClient = clientService.find(clientId);
  
  LOGGER.info("--- Client found ---");
  return foundClient;
 }
 
 @RequestMapping(value = "/{clientId}", method = RequestMethod.DELETE)
 @ResponseBody
 public void deleteClient(@PathVariable(value = "clientId") Integer clientId) {
  
  clientService.delete(clientId);
  LOGGER.info("--- Client deleted ---");
 }
 
}
Here we expose our service layer (in this case, our class annotated with @Service) via REST. To sum up the operations available, you can see this table:

URL Method type Operation
http://localhost:8080/spring-webapp-example/client-crud/rest-services/clients GET get all clients
http://localhost:8080/spring-webapp-example/client-crud/rest-services/clients POST create client
http://localhost:8080/spring-webapp-example/client-crud/rest-services/clients/1 PUT update client id = 1
http://localhost:8080/spring-webapp-example/client-crud/rest-services/clients/1 GET find client id = 1
http://localhost:8080/spring-webapp-example/client-crud/rest-services/clients/1 DELETE delete client id = 1

@Controller does the same job as the previous @Repository and @Service annotations; It tells Spring that this class is a Spring bean.

Clients
@XmlRootElement
@XmlAccessorType(XmlAccessType.PROPERTY)
public class Clients {
 
 private List<Client> clients;

 @XmlElement(name = "client")
 public List<Client> getClients() {
  return clients;
 }

 public void setClients(List<Client> clients) {
  this.clients = clients;
 }

}
This class acts as a wrapper for the list of client class. That wrapper eases the process of consuming a REST service that returns a list of objects. The wrapper class is annotated with JAXB annotations

Client
@XmlRootElement
@XmlAccessorType(XmlAccessType.PROPERTY)
@Entity
@Table(name = "T_CLIENT")
public class Client implements Serializable {

 private static final long serialVersionUID = -7682472386786656877L;
 
 @Id
 @GeneratedValue(strategy = GenerationType.SEQUENCE)
 private Integer id;
 private String name;

 public Integer getId() {
  return id;
 }

 public void setId(Integer id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

}
The Client JPA entity which is used by Hibernate, is annotated with JAXB elements too so that we can reuse the same entity when exposing it via REST. Of course you may create another Client class in order to expose only the information you want to expose.

Let's test this example!


ClientServiceTest
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/spring-beans-test.xml", "/applicationContext-servlet-test.xml" })
public class ClientServiceTest {
 
 @Autowired
 private ClientService clientService;
 
 private Client createNewClient() {
  Client client = new Client();
  client.setName("Rupert");
  
  return client;
 }
 
 @Test
 public void createTest() {
  
  Client client = createNewClient();
  
  Client clientSaved = clientService.create(client);
  
  Assert.assertNotNull(clientSaved);
  Assert.assertNotNull(clientSaved.getId());
 }
 
 @Test
 public void deleteTest() {
  Client client = createNewClient();
  
  Client clientSaved = clientService.create(client);
  clientService.delete(clientSaved.getId());
  Client clientDeleted = clientService.find(clientSaved.getId());

  Assert.assertNull(clientDeleted);
 }
 
 @Test
 public void findTest() {
  Client client = createNewClient();
  
  Client clientSaved = clientService.create(client);
  Client clientDeleted = clientService.find(clientSaved.getId());

  Assert.assertNotNull(clientDeleted);
 }
 
 @Test
 public void countTest() {
  Client client = createNewClient();
  
  long countBefore = clientService.count();
  clientService.create(client);
  long countAfter = clientService.count();
  
  Assert.assertEquals(countBefore, countAfter - 1);
 }
 
 @Test
 public void getAllTest() {
  this.createTest();
  List<Client> all = clientService.getAll();
  
  Assert.assertNotNull(all);
  Assert.assertTrue(all.size() > 0);
 }

}
This unit test is for the Client Service layer. You can run it with mvn test command.

ClientRestServiceIT
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/spring-beans-test.xml", "/applicationContext-servlet-test.xml" })
public class ClientRestServiceIT {
 
 private static final String REST_SERVICE_URL = "http://localhost:8080/spring-webapp-example/client-crud/rest-services/clients";
 private RestTemplate restTemplate = new RestTemplate();
 
 private Client createNewClient() {
  Client client = new Client();
  client.setName("Rupert");
  
  return client;
 }
 
 @Test
 public void createTest() {
  
  Client newClient = createNewClient();
  Client clientCreated = restTemplate.postForObject(REST_SERVICE_URL, newClient, Client.class);
  
  Assert.assertNotNull(clientCreated);
  Assert.assertNotNull(clientCreated.getId());
 }
 
 @Test
 public void updateTest() {
  
  Client newClient = createNewClient();
  Client clientCreated = restTemplate.postForObject(REST_SERVICE_URL, newClient, Client.class);
  
  clientCreated.setName("Stuart");
  
  String restServiceUrl = REST_SERVICE_URL + "/" + clientCreated.getId();
  restTemplate.put(restServiceUrl, clientCreated);
  Client clientModified = restTemplate.getForObject(restServiceUrl, Client.class);
  
  Assert.assertNotNull(clientModified);
  Assert.assertTrue(clientModified.getName().equals("Stuart"));
 }
 
 @Test
 public void findTest() {
  
  Client newClient = createNewClient();
  Client clientCreated = restTemplate.postForObject(REST_SERVICE_URL, newClient, Client.class);
  
  String restServiceUrlFind = REST_SERVICE_URL + "/" + clientCreated.getId();
  Client clientFound = restTemplate.getForObject(restServiceUrlFind, Client.class);
  
  Assert.assertNotNull(clientFound);
  Assert.assertEquals(clientFound.getId(), clientCreated.getId());
 }
 
 @Test
 public void getAllTest() {
  
  Client newClient = createNewClient();
  restTemplate.postForObject(REST_SERVICE_URL, newClient, Client.class);
  
  Clients clients = (Clients) restTemplate.getForObject(REST_SERVICE_URL, Clients.class);
  
  Assert.assertNotNull(clients);
  Assert.assertNotNull(clients.getClients());
  Assert.assertTrue(clients.getClients().size() > 0);
 }
 
 @Test
 public void deleteTest() {
  
  Client newClient = createNewClient();
  Client clientCreated = restTemplate.postForObject(REST_SERVICE_URL, newClient, Client.class);
  
  Assert.assertNotNull(clientCreated);
  Assert.assertNotNull(clientCreated.getId());
  
  //It should be found
  String restServiceUrlFind = REST_SERVICE_URL + "/" + clientCreated.getId();
  Client clientFound = restTemplate.getForObject(restServiceUrlFind, Client.class);
  Assert.assertNotNull(clientFound);
  Assert.assertNotNull(clientFound.getId());
  
  restTemplate.delete(restServiceUrlFind);
  
  //It should not be found
  Client clientDeleted = restTemplate.getForObject(restServiceUrlFind, Client.class);
  Assert.assertNull(clientDeleted);
 }
 
}
This test is the so called integration test we created. You can run it executing mvn verify.

About @Controller @Repository and @Service annotations

All of them do the same! they tell Spring that the class annotated is a Spring bean. So, why don't we use something like "@Bean" for every bean? Because the idea goes like this:
  • Every DAO should be @Repository
  • Every Controller/Action should be @Controller
  • Every Service should be @Service
Say, for instance, you have all of your beans annotated with @Controller (remember those 3 are the same) and you want to apply transactions via aspects with Spring to every Service class. Then, if you had all of your service beans annotated with @Service you could choose to apply transaction via aspects to every class annotated with @Service.

Download the complete example!

Checkout the project: https://subversion.assembla.com/svn/pablo-examples/spring-webapp-example

Run mvn test -> To run the unit tests only
Run mvn verify -> To run the unit tests + integration tests
Run mvn verify -Dmaven.test.skip=true -> To run integration tests only

Additionaly, you may run mvn eclipse:eclipse to convert it to Eclipse project

Wednesday, February 27, 2013

JavaUtils and Apache Common Collections

When it comes to the importance not to repeat yourself while writing code, it is even important to take a look at most common activities. For example, instead of writing a lot of nested for statements, making your code illegible, you can use already Java built-in features. Let's take a look at some really simple utils:

Tested with:
  • commons-collections-3.2.1
  • JUnit 4
  • Maven 3

  • CollectionUtils.select - If you want to retrieve one or more objects from a collection that meet your criteria (like id = 4 or age > 18)
  • CollectionUtils.find - If you want to retrieve only one object from a collection that meet your criteria (like id = 6)
  • Collections.max - If you want to retrieve only one object from a collection, the one which best meets one criteria
  • Collections.sort - If you want to have a collection ordered by some criteria

Data to base our examples on:
@Before
 public void init() {
  Person p1 = new Person(1, "ruben", 17);
  Person p2 = new Person(2, "carlos", 45);
  Person p3 = new Person(3, "ismael", 47);
  Person p4 = new Person(4, "raul", 30);

  personList.add(p1);
  personList.add(p2);
  personList.add(p3);
  personList.add(p4);
 }

CollectionUtils.select
@Test
 public void selectListTest() {
  AdultPredicate adultPredicate = new AdultPredicate();
  Collection adultPersons = CollectionUtils.select(personList, adultPredicate);
  
  Assert.assertNotNull(adultPersons);
  Assert.assertTrue(!adultPersons.isEmpty());
 }

public class AdultPredicate implements Predicate {
 
 @Override
 public boolean evaluate(Object arg0) {
  Person person = (Person) arg0;
  if (person.getAge() != null &&
   person.getAge() >= 18) {
   return true;
  }
  return false;
 }
}

CollectionUtils.find
@Test
 public void findObjectTest() {
  Predicate personNumberTwoPredicate = new PersonNumberTwoPredicate();
  Person personNumberTwo = (Person) CollectionUtils.find(personList, personNumberTwoPredicate);
  
  Assert.assertNotNull(personNumberTwo);
  Assert.assertTrue(personNumberTwo.getId().equals(2));
 }

public class PersonNumberTwoPredicate implements Predicate {

 private static final Integer PERSON_ID_TWO = 2;

 @Override
 public boolean evaluate(Object arg0) {
  Person person = (Person) arg0;
  if (person.getId().equals(PERSON_ID_TWO)) {
   return true;
  }
  return false;
 }
}

Collections.max
@Test
 public void oldestPersonTest() {
  PersonAgeComparator personAgeComparator = new PersonAgeComparator();
  Person oldestPerson = Collections.max(personList, personAgeComparator);
  
  Assert.assertNotNull(oldestPerson);
  Assert.assertTrue(oldestPerson.getAge().equals(47));
 }

public class PersonAgeComparator implements Comparator {

 @Override
 public int compare(Person o1, Person o2) {
  if (o1.getAge() > o2.getAge()) {
   return 1;
  }
  if (o1.getAge().equals(o2.getAge())) {
   return 0;
  }
  return -1;
 }
}

Collections.sort
@Test
 public void sortPersonsTest() {
  PersonAgeComparator personAgeComparator = new PersonAgeComparator();
  //Sort order age ascending
  Collections.sort(personList, personAgeComparator);
  //Sort order age descending
  Collections.sort(personList, ComparatorUtils.reversedComparator(personAgeComparator));
 }

Download the complete example here!

Checkout this: https://subversion.assembla.com/svn/pablo-examples/utils-test

Then from a Terminal get into that folder and run: mvn test
To import it into Eclipse IDE, from a Terminal run: mvn eclipse:eclipse and import it as a Java Project