Mostrando entradas con la etiqueta spring data. Mostrar todas las entradas
Mostrando entradas con la etiqueta spring data. Mostrar todas las entradas

miércoles, abril 26, 2017

Testing Spring Data + Spring Boot applications with Arquillian (Part 1)


Spring Data’s mission is to provide a familiar and consistent, Spring-based programming model for data access while still retaining the special traits of the underlying data store. It provides integration with several backend technologies such as JPA, Rest, MongoDB, Neo4J or Redis to cite a few.

So if you are using Spring (Boot) then Spring Data is the right choice to deal with persistence layer.

In next example you can see how simple is to use Spring Boot and Spring Data Redis.


It is important to notice that by default Spring Data Redis is configured to connect to localhost and port 6379, but you can override those values by setting system properties (spring.redis.host and spring.redis.port) or environment variables (SPRING_REDIS_HOST and SPRING_REDIS_PORT).

But now it is time to write a test for this piece of code. The main problem you might get is that you need a Redis server installed in all machines that need to execute these tests such as developers machine or Jenkins slaves. 

This is not a problem per se but when you start working on more and more projects you'll need more and more databases installed on the system, and what even can be worst not exactly the same version as required on production. 

To avoid this problem, one possible solution is using Docker and containers. So instead of relaying on having each database installed on the system, you only depends on Docker. Then the test just starts the repository container, in our case Redis, executes the test(s) and finally stops the container.

And this is where Arquillian (and Arquillian Cube) helps you on automating everything.
Arquillian Cube is an Arquillian extension that can be used to manager Docker containers from Arquillian.

To use Arquillian Cube you need a Docker daemon running on a computer (it can be local or not), but probably it will be at local.

By default the Docker server uses UNIX sockets for communicating with the Docker client. Arquillian Cube will attempt to detect the operating system it is running on and either set docker-java to use UNIX socket on Linux or to Boot2Docker/Docker-Machine on Windows/Mac as the default URI, so your test is portable across several Docker installations and you don't need to worry about configuring it, Arquillian Cube adapts to what you have installed.

Arquillian Cube offers three different ways to define container(s).
  • Defining a docker-compose file.
  • Defining a Container Object.
  • Using Container Object DSL.

For this post, Container Object DSL approach is the one used. To define a container to be started before executing tests and stopped after you only need to write next piece of code.

In this case a JUnit Rule is used to define which image should be used in the test (redis:3.2.6) and add as binding port the Redis port (6379).

The full test looks like:

Notice that it is a simple Spring Boot test using their bits and bobs, but Arquillian Cube JUnit Rule is used in the test to start and stop the Redis image.

Last important thing to notice is that test contains an implementation of ApplicationContextInitializer so we can configure environment with Docker data (host and binding port of Redis container) so Spring Data Redis can connect to correct instance.

Last but not least build.gradle file defines required dependencies, which looks like:


You can read more about Arquillian Cube at http://arquillian.org/arquillian-cube/

We keep learning,
Alex

Hercules and his gifts, Spiderman's control, And Batman with his fists, And clearly I don't see myself upon that list (Something just like this - The Chainsmokers & Coldplay)

Music: https://www.youtube.com/watch?v=FM7MFYoylVs

martes, septiembre 23, 2014

Java EE + MongoDb with Apache TomEE and Jongo Starter Project



Know MongoDB and Java EE, but you don't know exactly how to integrate both of them? Do you read a lot about the topic but you have not found a solution which fits this purpose? This starter project is for you:

You will learn how to use MongoDB and Java EE in a fashion way without having to depend on Spring Data MongoDB framework but with "similar" basic features.

The only thing better than a Maven archetype is a repository you can fork with everything already setup. Skip the documentation and just fork-and-code. This starter project contains:
The example is pretty simple, we want to store colors inside a MongoDB collection.

Our POJO is like:


Note that we are using @ObjectId annotation provided by Jongo to set this field as MongoDB id. Moreover because it is called _id, the id will be set automatically.

Then the service layer:


Note that there isn't a lot of code, but some points are really interesting stuff. Let's analyze them.

@Singleton is used to define an EJB as singleton, it works with @Stateless as well, for Java EE users no news here.

The class is abstract. Why? Because it allows us to not implement all methods but define them.

Also implements java.lang.reflect.InvocationHandler. This is because we want to use one really interesting feature which allows us to create a fallback method called invoke. For any method defined but not implemented this method is called.

We have a MongoCollection class (from Jongo project) that it is injected. MongoCollection represents a collection in MongoDB. Because we need to set which collection we want to work with, an annotation called @JongoCollection is created so you can pass the name of the backend collection. Note that MongoCollection is produced by CDI container by using our custom producer. Again no news here for CDI users.


Then there is a lot of methods which represents CRUD operations. Note that they are not implemented, they are only annotated with @Insert, @Find, @Remove, ... to set which is the purpose of the method we want to execute. Some of them like finders or removers can receive Jongo-like query to be executed. And also a method called countColors which as you can see you can implement as custom method without relying to logic implemented within invoke method.

And finally the invoke method. This method will be called for all abstract methods, and simply sends to PersistenceHandler class, which in fact is a util class against Jongo to execute the required operation.

And that's all, quite simple, and if you want to add new abstract operations, you only need to implement them inside PersistenceHandler class.

Some of you may wonder why I use annotations and not the typical Spring Data approach where the name of the method indicates the operation. You can implement this approach as well, it is a simple matter of creating a regular expression inside PersistenceHandler class instead of if/else with annotations, but I prefer annotations approach. Faster in execution time, clean, and for example you can refactor the annotation name from @Find to @Buscar (Spanish equivalent) without worrying if you are breaking some regular expression.

And finally the test:


This is an Arquillian test that has nothing special apart from one line:

.addAsManifestResource(new StringAsset(MONGODB_RESOURCE), "resources.xml")

Because we are using Apache TomEE we use the way it has to configure elements to be used as javax.annotation.Resource in our code.

The META-INF/resources.xml content will be:


and then we use in our MongoClient producer to create the MongoClient instance to be used inside code. Note that we are using @Resource as any standard resource like DataSource, but in fact MongoClientURI is injected:


so in fact Mongo connection is configured in META-INF/resources.xml file and thanks of TomEE we can refer it as any standard resource.

If you are going to use other application server you can change this approach to the one provided by it, or if you want you can use DeltaSpike extensions or your own method. Also because MongoClient database is get from a method annotated with @Produces  you can be injected it wherever you want on your code, so you can skip the abstract services layer if you want.

What are the benefits of this approach?

First that it is Java EE solution, you can use it without depending on Spring framework or any other library. You implement what you need, you do not download a bunch of libraries simply for accessing a MongoDB with some kind of object mapping.

Also as you may see, the code is quite simple and there is no magic behind it, you can debug it without any problem, or even improve or change depending on your needs. The code is yours and is waiting to be modified. Do you want to use native MongoDB objects instead of Jongo? No problem, you can implement it. Moreover there aren't much layers, in fact only one (the PersistenceHandler) so the solution is pretty fast in terms of execution.

Of course this do not mean that you can't use Spring Data MongoDB. It is a really interesting framework, so if you are already using Spring, go ahead with it, but if you plan to use a full Java EE solution, then clone this project and start using MongoDB without having to make some research on the net about how to integrate both of them.

You can clone the project from https://github.com/lordofthejars/tomee-mongodb-starter-project

We keep learning,
Alex.
I'm driving down to the barrio, Going 15 miles an hour cause I'm already stoned, Give the guy a twenty and wait in the car, He tosses me a baggie then he runs real far (Mota - The Offspring)

Music: https://www.youtube.com/watch?v=xS5_TO8lyF8