In a previous post I put here how to create fat jars using Maven, now Let’s see how to copy the necessary dependencies, setup the classpath and execute the jar without unpacking any of the dependencies.

To do this we’ll need two plugins :

maven-jar-plugin

maven-dependency-plugin

maven-jar-plugin is the one that will create and configure META-INF/MANIFEST.MF containing the main class and all the related dependencies.

maven-dependency-plugin will pickup and put all the dependencies in the right place.

Let’s take a look.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <groupId>java4-fun</groupId>
   <artifactId>copy-dependencies</artifactId>
   <version>1.0-SNAPSHOT</version>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>
      <!-- Dependencies -->
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
               <source>${java.version}</source>
               <target>${java.version}</target>
            </configuration>
         </plugin>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
               <archive>
                  <manifest>
                     <addClasspath>true</addClasspath>
                     <classpathPrefix>lib/</classpathPrefix>
                     <mainClass>org.jboss.weld.environment.se.StartMain</mainClass>
                  </manifest>
               </archive>
            </configuration>
         </plugin>
         <plugin>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
               <execution>
                  <phase>package</phase>
                  <goals>
                     <goal>copy-dependencies</goal>
                  </goals>
                  <configuration>
                     <outputDirectory>${project.build.directory}/lib</outputDirectory>
                  </configuration>
               </execution>
            </executions>
         </plugin>
      </plugins>
   </build>
</project>

Using this configuration, all our dependencies will be placed into /lib folder and the jar will be created in the same folder level, ready to be executed.

A few days ago I had to write an application with some peculiarities that drove me to do something that I didn’t before, creating JPA entity managers programmatically, pretty interesting actually, I managed to create the persistence units that I need dynamically and according to the environment easily.

To make it simple I’ll not put all of them here, neither the full code, just the necessary snippets to help someone that is trying to do this.

persistence.xml

Even if you are going to use this approach, even if you have many different environments, one persistence.xml still necessary.

<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
             version="2.1">
   <persistence-unit name="default">
   </persistence-unit>
</persistence>

EntityManagerFactory and EntityManager

Here you can see that it’s a MongoDB em and that used some CDI but don’t mind about that, the relevant parts are the properties and the EntityManager creation.

package java4.fun.producer;

import javax.enterprise.inject.Produces;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import java.util.HashMap;
import java.util.Map;

public class Producer {

   @Produces
   public EntityManager getEntityManager() {
      final Map<String, String> properties = new HashMap<>();

      properties.put("javax.persistence.provider", "org.hibernate.ogm.jpa.HibernateOgmPersistence");
      properties.put("javax.persistence.transactionType", "RESOURCE_LOCAL");
      properties.put("hibernate.ogm.datastore.provider", "mongodb");
      properties.put("hibernate.ogm.datastore.grid_dialect", "org.hibernate.ogm.datastore.mongodb.MongoDBDialect");
      properties.put("hibernate.ogm.datastore.database", "allandequeiroz");
      properties.put("hibernate.ogm.mongodb.host", "127.0.0.1");
      properties.put("hibernate.ogm.datastore.create_database", "false");
      properties.put("hibernate.ogm.mongodb.username", "");
      properties.put("hibernate.ogm.mongodb.password", "");

      final EntityManagerFactory factory = Persistence.createEntityManagerFactory("default", properties);
      return factory.createEntityManager();
   }
}

The Repository

How I used CDI, the EntityManager dependency was easily injected.

package java4.fun.repository;

import javax.inject.Inject;
import javax.persistence.EntityManager;

public class ArticleRepository {

   private EntityManager entityManager;

   @Inject
   public ArticleRepository(EntityManager entityManager) {
      this.entityManager = entityManager;
   }
}

The Client

This is how the dependency was injected in here, another simple @Inject annotation.

package java4.fun;

import java4.fun.repository.ArticleRepository;
import org.jboss.weld.environment.se.bindings.Parameters;
import org.jboss.weld.environment.se.events.ContainerInitialized;

import javax.enterprise.event.Observes;
import javax.inject.Inject;
import java.util.List;
import java.util.logging.Logger;

public class Main {

   private static final Logger LOG = Logger.getLogger(Main.class.getName());

   @Inject
   private ArticleRepository repository;

   public void main(@Observes ContainerInitialized event, @Parameters List<String> args) {
      System.exit(0);
   }
}

Configuration and Dependencies

Now, the dependencies, just in case you wanna try 🙂

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <groupId>java4.fun</groupId>
   <artifactId>programmatically-entity-manager</artifactId>
   <version>1.0-SNAPSHOT</version>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>

      <!-- Lombook -->
      <dependency>
         <groupId>org.projectlombok</groupId>
         <artifactId>lombok</artifactId>
         <version>1.16.6</version>
      </dependency>

      <!-- Logging -->
      <dependency>
         <groupId>org.slf4j</groupId>
         <artifactId>slf4j-log4j12</artifactId>
         <version>1.7.22</version>
      </dependency>

      <!-- Weld -->
      <dependency>
         <groupId>org.jboss.weld.se</groupId>
         <artifactId>weld-se-core</artifactId>
         <version>2.4.1.Final</version>
      </dependency>
      <dependency>
         <groupId>org.jboss.weld</groupId>
         <artifactId>weld-core</artifactId>
         <version>2.4.1.Final</version>
      </dependency>

      <!-- Hibernate -->
      <dependency>
         <groupId>org.hibernate.ogm</groupId>
         <artifactId>hibernate-ogm-mongodb</artifactId>
         <version>5.0.4.Final</version>
      </dependency>
      <dependency>
         <groupId>org.hibernate.ogm</groupId>
         <artifactId>hibernate-ogm-core</artifactId>
         <version>5.0.4.Final</version>
      </dependency>
      <dependency>
         <groupId>org.hibernate.common</groupId>
         <artifactId>hibernate-commons-annotations</artifactId>
         <version>5.0.1.Final</version>
      </dependency>
      <dependency>
         <groupId>org.hibernate</groupId>
         <artifactId>hibernate-core</artifactId>
         <version>5.1.0.Final</version>
      </dependency>
      <dependency>
         <groupId>org.hibernate</groupId>
         <artifactId>hibernate-entitymanager</artifactId>
         <version>5.1.0.Final</version>
      </dependency>
      <dependency>
         <groupId>org.hibernate.javax.persistence</groupId>
         <artifactId>hibernate-jpa-2.0-api</artifactId>
         <version>1.0.1.Final</version>
      </dependency>

      <!-- Utils -->
      <dependency>
         <groupId>commons-lang</groupId>
         <artifactId>commons-lang</artifactId>
         <version>2.6</version>
      </dependency>
      <dependency>
         <groupId>commons-collections</groupId>
         <artifactId>commons-collections</artifactId>
         <version>3.2.1</version>
      </dependency>
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
               <source>${java.version}</source>
               <target>${java.version}</target>
            </configuration>
         </plugin>
         <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <configuration>
               <archive>
                  <manifest>
                     <mainClass>org.jboss.weld.environment.se.StartMain</mainClass>
                  </manifest>
               </archive>
               <descriptorRefs>
                  <descriptorRef>jar-with-dependencies</descriptorRef>
               </descriptorRefs>
            </configuration>
            <executions>
               <execution>
                  <id>make-assembly</id>
                  <phase>package</phase>
                  <goals>
                     <goal>single</goal>
                  </goals>
               </execution>
            </executions>
         </plugin>
      </plugins>
   </build>
</project>

 

In this quick tip, let’s take a look at how to create Uber jars with maven.

Uber jars or Fat jars, are quite useful, especially when we’re creating self-contained and executable applications that we’re planning to distribute and make it useful with less effort possible.

A good option to do this is using Apache Maven Assembly Plugin. Let’s take a look in the example below.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <groupId>java4.fun</groupId>
   <artifactId>uber-jar</artifactId>
   <version>1.0-SNAPSHOT</version>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>
      <!-- Dependencies -->
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
               <source>${java.version}</source>
               <target>${java.version}</target>
            </configuration>
         </plugin>
         <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <configuration>
               <archive>
                  <manifest>
                     <mainClass>org.jboss.weld.environment.se.StartMain</mainClass>
                  </manifest>
               </archive>
               <descriptorRefs>
                  <descriptorRef>jar-with-dependencies</descriptorRef>
               </descriptorRefs>
            </configuration>
            <executions>
               <execution>
                  <id>make-assembly</id>
                  <phase>package</phase>
                  <goals>
                     <goal>single</goal>
                  </goals>
               </execution>
            </executions>
         </plugin>
      </plugins>
   </build>
</project>

Here we’re creating a jar that contains all the dependencies “jar-with-dependencies” ready to be executed, we just need to specify the mainClass to be set into META-INF/MANIFEST.MF and build it.

That’s it, simple and useful 🙂

Using spring-data to access MongoDB in Java is quite interesting since the primary goal of Spring Data project is to make it easier to use and it does 🙂

Maven configuration.

That’s the configuration that I used for this simple sample. Notice that I used maven-assembly-plugin do create a fat jar and execute it as a standalone app, may you prefer using something fancy like Spring Boot.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <groupId>java4.fun.data</groupId>
   <artifactId>oracle-to-mongo</artifactId>
   <version>1.0-SNAPSHOT</version>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.projectlombok</groupId>
         <artifactId>lombok</artifactId>
         <version>1.16.6</version>
      </dependency>

      <!-- Spring -->
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-core</artifactId>
         <version>4.2.4.RELEASE</version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-context</artifactId>
         <version>4.1.6.RELEASE</version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-aop</artifactId>
         <version>4.2.4.RELEASE</version>
      </dependency>
      <dependency>
         <groupId>org.springframework.data</groupId>
         <artifactId>spring-data-mongodb</artifactId>
         <version>1.9.6.RELEASE</version>
      </dependency>
      <dependency>
         <groupId>org.mongodb</groupId>
         <artifactId>mongodb-driver</artifactId>
         <version>3.4.1</version>
      </dependency>
   </dependencies>
   <build>
      <plugins>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
               <source>${java.version}</source>
               <target>${java.version}</target>
            </configuration>
         </plugin>
         <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <configuration>
               <archive>
                  <manifest>
                     <mainClass>java4.fun.data.Main</mainClass>
                  </manifest>
               </archive>
               <descriptorRefs>
                  <descriptorRef>jar-with-dependencies</descriptorRef>
               </descriptorRefs>
            </configuration>
            <executions>
               <execution>
                  <id>make-assembly</id>
                  <phase>package</phase>
                  <goals>
                     <goal>single</goal>
                  </goals>
               </execution>
            </executions>
         </plugin>
      </plugins>
   </build>
</project>

 

Spring configuration

Next, let’s create the files that will compose the spring configurations, in this case, let’s create them into “src/main/resources”.

application.properties

mongodb.host=localhost
mongodb.host.port=27017
mongodb.database=technicalanalyzer

applicationContext.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"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mongo="http://www.springframework.org/schema/data/mongo"
       xsi:schemaLocation=
             "http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context-3.0.xsd
          http://www.springframework.org/schema/data/mongo
          http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
          http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <context:property-placeholder location="classpath*:application.properties"/>

   <mongo:mongo id="mongo" host="${mongodb.host}" port="${mongodb.host.port}"/>
   <mongo:repositories base-package="java4.fun.data.mongo.repository" />

   <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
      <constructor-arg ref="mongo" />
      <constructor-arg name="databaseName" value="${mongodb.database}" />
   </bean>

   <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

   <context:annotation-config />
   <context:component-scan base-package="java4.fun.data"/>

</beans>

 

Model

Now a really simple model with just an Id and a Title.

import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Data
@Document(collection="ArticleEntity")
public class ArticleEntity {
   @Id
   private long articleId;
   private String title;
}

OBS : @Data is a Lombook annotation.

 

Spring Service

import java4.fun.data.mongo.entity.ArticleEntity;
import java4.fun.data.mongo.repository.MongoArticleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class MongoArticleService {

   private final MongoArticleRepository repository;

   @Autowired
   public MongoArticleService(final MongoArticleRepository repository) {
      this.repository = repository;
   }

   public ArticleEntity save(ArticleEntity article) {
      return repository.save(article);
   }
}

 

Spring Repository

This is a good one, since Spring offers default implementations for CrudRepository like SimpleMongoRepository to perform basic operations (even those not so basic), it’s not necessary to write anything, just create an interface that extends CrudRepository.

import java4.fun.data.mongo.entity.ArticleEntity;
import org.springframework.data.repository.CrudRepository;

public interface MongoArticleRepository extends CrudRepository<ArticleEntity, Long> {
}

That’s it, this is our CRUD.

 

Main

import java4.fun.data.mongo.entity.ArticleEntity;
import java4.fun.data.mongo.service.MongoArticleService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

import java.util.logging.Level;
import java.util.logging.Logger;

public class Main {

   private static final Logger LOG = Logger.getLogger(Main.class.getName());
   private static final int OK = 0;
   private static final int NOK = 1;

   public static void main(String... args) throws ClassNotFoundException {
      final ApplicationContext ctx = new GenericXmlApplicationContext("applicationContext.xml");

      try {

         final MongoArticleService mongoArticleService = ctx.getBean(MongoArticleService.class);

         final ArticleEntity articleEntity = getDummyArticleEntity();
         mongoArticleService.save(articleEntity);

      } catch (Exception e) {
         LOG.log(Level.SEVERE, e.getMessage());
         System.exit(NOK);
      }

      System.exit(OK);
   }

   private static ArticleEntity getDummyArticleEntity() {
      final ArticleEntity articleEntity = new ArticleEntity();
      articleEntity.setTitle("Spring!");
      return articleEntity;
   }
}

Observe that I’m just saving here but you can try any other operations available. If you want to learn more and try something else you can check the documentation.

the User Guide

the JavaDocs

the home page of Spring Data MongoDB

Today I’ll write down here my configurations to get Docker bash completion working, looks like a simple thing but I saw some difficulties to get it done properly here and there so.

1# Install Homebrew

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

2# Install bash-completion and wget

$ brew install bash-completion
$ brew tap homebrew/completions

3# Update your .bash_profile or .bashrc to execute bash_completion when you open a new terminal

If you prefer to edit, use your editor to add this content :
if [ -f $(brew --prefix)/etc/bash_completion ]; then
. $(brew --prefix)/etc/bash_completion
fi

Or to append this content :

cat >> ~/.bash_profile <<EOL
if [ -f $(brew --prefix)/etc/bash_completion ]; then
. $(brew --prefix)/etc/bash_completion
fi
EOL

4# Create the aliases to completions

$ cd /usr/local/etc/bash_completion.d
$ ln -s /Applications/Docker.app/Contents/Resources/etc/docker.bash-completion
$ ln -s /Applications/Docker.app/Contents/Resources/etc/docker-machine.bash-completion
$ ln -s /Applications/Docker.app/Contents/Resources/etc/docker-compose.bash-completion

5# reload your .bash*

$ source ~/.bash_profile

That’s it, now you cant try for example

$ docker [tab]
$ docker-compose [tab]
$ docker-machine [tab]