Maven, Hibernate, PrimeFaces and Jetty

The final project structure

In this post, we will make a (very) simple CRUD application using Maven, Hibernate, PrimeFaces and Jetty. It won’t be the best application out there, but enough to get started. Run ‘mvn jetty:run’ to start the application.

Click here to download the actual project.

In this case, we’ll be making a simple addressbook, with each contact having a first and last name, and an address. The address will have a city, street, housenumber and postalcode. They will each have an id, because they need to be stored somewhere. This is what they look like:

package nl.ghyze.contacts;

public class Contact {

    private Long id;
    private String firstname;
    private String lastname;
    private Address address;

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

    public Long getId(){
        return id;
    }

    public void setFirstname(String firstname){
        this.firstname = firstname;
    }

    public void setLastname(String lastname){
        this.lastname = lastname;
    }

    public String getFirstname() {
        return firstname;
    }

    public String getLastname() {
        return lastname;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public Address getAddress() {
        return address;
    }
}
package nl.ghyze.contacts;

public class Address {

    private Long id;
    private String city;
    private String street;
    private String housenumber;
    private String postalcode;

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

    public Long getId() {
        return id;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getCity() {
        return city;
    }

    public void setStreet(String street) {
        this.street = street;
    }

    public String getStreet() {
        return street;
    }

    public void setHousenumber(String housenumber) {
        this.housenumber = housenumber;
    }

    public String getHousenumber() {
        return housenumber;
    }

    public void setPostalcode(String postalcode) {
        this.postalcode = postalcode;
    }

    public String getPostalcode() {
        return postalcode;
    }
}

Of course there needs to be a database schema to store the records in. We will use a MySQL database for this. For simplicity, all keys are bigints, and all other fields will be varchars.

create schema if not exists contacts;
use contacts;

create table if not exists address
(id bigint primary key,
city varchar(100),
postalcode varchar(10),
housenumber varchar(10),
street varchar(100)
);

create table if not exists contact
(id bigint primary key,
firstname varchar(255),
lastname varchar(255),
addressId bigint);

Now we will need to tell Hibernate how to map the database tables to objects. These days you’ll probably use annotations for that, but to keep database-related code out of our entities, we’re going for XML configuration.
The mapping for contact will look like this:

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="nl.ghyze.contacts">
    <class name="Contact" table="contact">
        <id name="id" column="id">
            <generator class="increment" />
        </id>
        <property name="firstname" column="firstname" />
        <property name="lastname" column="lastname" />
        <one-to-one name="address" class="nl.ghyze.contacts.Address" cascade="save-update" />
    </class>
</hibernate-mapping>

And the mapping for Address:

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="nl.ghyze.contacts">
    <class name="Address" table="address">
        <id name="id" column="id">
            <generator class="increment" />
        </id>
        <property name="city" column="city" />
        <property name="postalcode" column="postalcode" />
        <property name="housenumber" column="housenumber" />
        <property name="street" column="street" />
    </class>
</hibernate-mapping>

Now we need to configure hibernate, telling it how to connect to our database and which mapping files to use.

<?xml version='1.0' encoding='utf-8'?>

<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>
        <!-- Database connection settings -->
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost:3306/contacts?useUnicode=true&amp;useJDBCCompliantTimezoneShift=true&amp;useLegacyDatetimeCode=false&amp;serverTimezone=UTC</property>
        <property name="connection.username">root</property>
        <property name="connection.password">password</property>

        <!-- JDBC connection pool (use the built-in) -->
        <property name="connection.pool_size">1</property>

        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

        <!-- Disable the second-level cache -->
        <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>

        <!-- Do not show executed SQL -->
        <property name="show_sql">false</property>

        <!-- Validate the database schema on startup -->
        <property name="hbm2ddl.auto">validate</property>

        <!-- Use these mapping files -->
        <mapping resource="nl/ghyze/contacts/Contact.hbm.xml"/>
        <mapping resource="nl/ghyze/contacts/Address.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

Next step, setting up the connection from our application. Since we want only one place to manage the database connectivity in the application, this will be set up as a Singleton.

package nl.ghyze.contacts.repository;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;

public class DatabaseSessionProvider {

	private static final DatabaseSessionProvider instance = new DatabaseSessionProvider();

	private SessionFactory sessionFactory;
	
	private DatabaseSessionProvider(){
		setUp();
	}
	
	public static DatabaseSessionProvider getInstance(){
		return instance;
	}
	
	public Session getSession(){
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		return session;
	}

	public void end(Session session){
		if (session.getTransaction().getRollbackOnly()){
			rollback(session);
		} else {
			commit(session);
		}
	}

	private void commit(Session session){
		session.getTransaction().commit();
		session.close();
	}

	private void rollback(Session session){
		session.getTransaction().rollback();
		session.close();
	}

	public void shutDown(){
		sessionFactory.close();
	}

	private void setUp() {
		final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
				.configure()
				.build();
		try {
			sessionFactory = new MetadataSources( registry ).buildMetadata().buildSessionFactory();
		}
		catch (Exception e) {
			e.printStackTrace();
			StandardServiceRegistryBuilder.destroy( registry );
		}
	}
}

At this point we’re ready to read, write and delete contacts from and to the database. We’re going to use HQL for this purpose.

package nl.ghyze.contacts.repository;

import nl.ghyze.contacts.Contact;
import org.hibernate.Session;
import org.hibernate.query.Query;

import java.util.List;

public class ContactRepository {

    private final DatabaseSessionProvider provider;
    private Session session;

    public ContactRepository(){
        this.provider = DatabaseSessionProvider.getInstance();
    }

    public Contact saveContact(Contact contact){
        session = provider.getSession();
        session.saveOrUpdate(contact);
        provider.end(session);
        return contact;
    }

    public List<Contact> getAllContacts(){
        String queryString = "from Contact";
        Query<Contact> query = createQuery(queryString);
        List<Contact> result = query.getResultList();
        provider.end(session);
        return result;
    }

    public void deleteContact(Contact contact){
        session = provider.getSession();
        session.delete(contact);
        provider.end(session);
    }

    public Contact getContactWithId(Long id){
        if (id == null){
            return null;
        }
        String queryString = "from Contact where id = :id";
        Query<Contact> query = createQuery(queryString);
        query.setParameter("id", id);
        Contact contact = query.getSingleResult();
        provider.end(session);
        return contact;
    }

    private Query<Contact> createQuery(String queryString) {
        session = provider.getSession();
        return session.createQuery(queryString, Contact.class);
    }
}

With the database stuff out of the way, let’s create a simple service for communicating with the repository. At this point we’re getting into PrimeFaces. We’re making this a ManagedBean, so it can be injected into the Action classes that we’ll discuss next.

package nl.ghyze.contacts.service;

import nl.ghyze.contacts.Address;
import nl.ghyze.contacts.Contact;
import nl.ghyze.contacts.repository.ContactRepository;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import java.util.List;

@ManagedBean(name="contactService")
@SessionScoped
public class ContactService {

    private ContactRepository contactRepository = new ContactRepository();

    public List<Contact> getContactList(){
        return contactRepository.getAllContacts();
    }

    public Contact saveContact(Contact contact){
        return contactRepository.saveContact(contact);
    }

    public Contact getOrCreateContact(Long id){
        Contact contact =  contactRepository.getContactWithId(id);
        if (contact == null){
            contact = new Contact();
        }
        if (contact.getAddress() == null){
            contact.setAddress(new Address());
        }
        return contact;
    }

    public void deleteContact(Contact contact) {
        contactRepository.deleteContact(contact);
    }
}

Before we continue, let’s take a moment to think about the front-end of the application. We’re going to make two pages: the first one listing all the contacts that we have, and the second one listing the details of one single contact. Each page will have its own backing class, handling the server side actions of the requests.
The list action will be simple: it only needs to provide a list of Contacts that is currently in our database.

package nl.ghyze.contacts.web;

import nl.ghyze.contacts.Contact;
import nl.ghyze.contacts.service.ContactService;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import java.util.List;

@ManagedBean(name="contactListAction")
@SessionScoped
public class ContactListAction {

    @ManagedProperty(value="#{contactService}")
    private ContactService contactService;

    public List<Contact> getContactList(){
        return contactService.getContactList();
    }

    public void setContactService(ContactService contactService){
        this.contactService = contactService;
    }

    public ContactService getContactService(){
        return contactService;
    }
}

The details action will be a bit more complicated. It will need to be able to:
– get the correct contact
– save the edited contact
– delete a contact
– Since everything is SessionScoped, when the user wants to go back to the list, it needs to clear its values
The methods that receive an ActionEvent as parameter are called from PrimeFaces. Pay attention to the method signature, as this is something that lots of developers struggle with.

package nl.ghyze.contacts.web;

import nl.ghyze.contacts.Contact;
import nl.ghyze.contacts.service.ContactService;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import java.io.IOException;

@ManagedBean
@SessionScoped
public class ContactDetailAction {

    @ManagedProperty(value="#{contactService}")
    private ContactService contactService;

    private Contact contact;

    private Long contactId;

    public Contact getContact(){
        if (contact == null){
            contact = contactService.getOrCreateContact(contactId);
        }
        return contact;
    }

    public void save(ActionEvent actionEvent){
        contact = contactService.saveContact(contact);
        redirectToList();
    }

    public void delete(ActionEvent actionEvent){
        contactService.deleteContact(contact);
        redirectToList();
    }

    public void back(ActionEvent actionEvent){
        redirectToList();
    }

    private void redirectToList() {
        reset();
        ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
        try {
            context.redirect(context.getRequestContextPath() + "/contactList.xhtml");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void reset() {
        contact = null;
        contactId = null;
    }

    public void setContactService(ContactService contactService){
        this.contactService = contactService;
    }

    public ContactService getContactService(){
        return contactService;
    }

    public void setContactId(Long id){
        this.contactId = id;
    }

    public Long getContactId(){
        return contactId;
    }
}

Now we’re ready to create the .xhtml pages. For the list, we’re going to create a table for listing all contacts. The last column will have buttons, so we can edit the contact in that row. Clicking this button will navigate to the details page, supplying the ID of the contact. Below the table there will be a button for adding new contacts.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:p="http://primefaces.org/ui">

    <h:head>
        <title>Addressbook</title>
    </h:head>
    <h:body>
        <h:form>
            <p:panel header="Contact list">
               <p:dataTable var="contact" value="#{contactListAction.contactList}">
                   <p:column headerText="First name">
                       <h:outputText value="#{contact.firstname}"/>
                   </p:column>
                   <p:column headerText="Last name">
                       <h:outputText value="#{contact.lastname}"/>
                   </p:column>
                   <p:column headerText="Street">
                       <h:outputText value="#{contact.address.street}"/>
                   </p:column>
                   <p:column headerText="Housenumber">
                       <h:outputText value="#{contact.address.housenumber}"/>
                   </p:column>
                   <p:column headerText="Postal code">
                       <h:outputText value="#{contact.address.postalcode}"/>
                   </p:column>
                   <p:column headerText="City">
                       <h:outputText value="#{contact.address.city}"/>
                   </p:column>
                   <p:column style="width:32px;text-align: center">
                       <p:button icon="ui-icon-edit" title="Edit" outcome="contactDetail">
                            <f:param name="contactId" value="#{contact.id}" />
                       </p:button>
                   </p:column>
               </p:dataTable>
                <p:button outcome="contactDetail" value="new Contact"/>
            </p:panel>
        </h:form>
    </h:body>
</html>

The details page is, again, a bit more complicated. This page receives the contactId, and sets it in the action. This part is a bit confusing, and it takes a while to understand. The f:metadata tag is responsible for this.
The p:commandButton tags are used to call methods in ContactDetailsAction. This is how those methods that take the ActionEvent parameters are called.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:p="http://primefaces.org/ui" xmlns:c="http://java.sun.com/jstl/core" xmlns:f="http://java.sun.com/jsf/core">

    <h:head>
        <title>Edit Contact</title>
    </h:head>

    <h:body>
        <f:metadata>
            <f:viewParam name="contactId" value="#{contactDetailAction.contactId}" />
        </f:metadata>
        <h:form>
            <c:set var="contact" value="#{contactDetailAction.contact}"/>
            <p:panel header="Edit Contact">
                <h:panelGrid columns="2" cellpadding="4">
                    <h:outputText value="First name"/>
                    <h:inputText value="#{contact.firstname}"/>

                    <h:outputText value="Last name"/>
                    <h:inputText value="#{contact.lastname}"/>

                    <h:outputText value="Street" />
                    <h:inputText value="#{contact.address.street}"/>

                    <h:outputText value="Housenumber" />
                    <h:inputText value="#{contact.address.housenumber}"/>

                    <h:outputText value="Postal code" />
                    <h:inputText value="#{contact.address.postalcode}"/>

                    <h:outputText value="City" />
                    <h:inputText value="#{contact.address.city}"/>
                </h:panelGrid>
                <p:commandButton value="Save" actionListener="#{contactDetailAction.save}" ajax="false" />
                <p:commandButton value="Delete" actionListener="#{contactDetailAction.delete}" ajax="false" />
                <p:commandButton value="Back to list" actionListener="#{contactDetailAction.back}" ajax="false" />
            </p:panel>
        </h:form>
    </h:body>
</html>

The Deployment Descriptor (web.xml) tells the application server how to handle incomming requests.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">

    <!-- File(s) appended to a request for a URL that is not mapped to a web component -->
    <welcome-file-list>
        <welcome-file>contactList.xhtml</welcome-file>
    </welcome-file-list>

    <!-- Define the JSF servlet (manages the request processing life cycle for JavaServer Faces) -->
    <servlet>
        <servlet-name>faces-servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- Map following files to the JSF servlet -->
    <servlet-mapping>
        <servlet-name>faces-servlet</servlet-name>
        <url-pattern>*.xhtml</url-pattern>
    </servlet-mapping>
</web-app>

The maven project configuration (pom.xml) tells maven how to build this project. It contains all the dependencies. Pay attention to the last part of the configuration, the maven-jetty-plugin. This is how we start, and test, the application.

<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>nl.ghyze</groupId>
  <artifactId>addressbook</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>addressbook</name>
  <url>http://maven.apache.org</url>

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

    <servlet.version>3.1.0</servlet.version>
    <jsf.version>2.2.13</jsf.version>
    <primefaces.version>6.0</primefaces.version>

    <maven-compiler-plugin.version>3.5.1</maven-compiler-plugin.version>
    <jetty-maven-plugin.version>9.4.0.M0</jetty-maven-plugin.version>

    <hibernate.version>5.2.1.Final</hibernate.version>
    <mysql.version>6.0.3</mysql.version>
  </properties>

  <dependencies>
    <!-- PrimeFaces -->
    <dependency>
      <groupId>org.primefaces</groupId>
      <artifactId>primefaces</artifactId>
      <version>${primefaces.version}</version>
    </dependency>
    <!-- Servlet -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>${servlet.version}</version>
      <scope>provided</scope>
    </dependency>
    <!-- JSF -->
    <dependency>
      <groupId>com.sun.faces</groupId>
      <artifactId>jsf-api</artifactId>
      <version>${jsf.version}</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>com.sun.faces</groupId>
      <artifactId>jsf-impl</artifactId>
      <version>${jsf.version}</version>
      <scope>compile</scope>
    </dependency>

    <!-- Database-->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>${hibernate.version}</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>${mysql.version}</version>
    </dependency>

  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.5.1</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-maven-plugin</artifactId>
        <version>${jetty-maven-plugin.version}</version>
        <configuration>
          <httpConnector>
            <port>9090</port>
          </httpConnector>
          <webApp>
            <contextPath>/address</contextPath>
          </webApp>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

Split condition

Intuitively it makes sense to group several statements in an if/else clause. In that case you only need to execute the check once. However, this is not always the cleanest solution, and it makes methods longer than they should be.

For example, take the following piece of code.

    public void updateDocument(Attachment attachment){
        Document document = new Document();
        if (AttachmentModel.TYPE_SPECIAL.equals(attachment.getAttachmentType())) {
            DocumentType documentType = repository.findByCode(DocumentType.class, DocumentType.CODE_SPECIAL);
            document.setType(documentType);
            document.setName(documentType.getName() + " " + getDateAsString());
        } else {
            document.setType(repository.findByCode(DocumentType.class, DocumentType.CODE_OTHER));
            document.setName("Attachment " + getDateAsString());
        }
    }

So, what’s wrong with this? It does what it’s supposed to do, and it doesn’t look too complicated.

But it does too many things:

  1. It checks the type of the attachment
  2. Based on this type, it finds the DocumentType from the database
  3. It sets the DocumentType of the Document
  4. It generates a name
  5. It sets the name of the document

To cite Uncle Bob (Clean Code, page 35):

Functions should do one thing. They should do it well. They should do it only.

So, let’s refactor.

First, copy the condition, and move the statements around so that each condition handles only one property of the document.

    public void updateDocument(Attachment attachment){
        Document document = new Document();
        if (AttachmentModel.TYPE_SPECIAL.equals(attachment.getAttachmentType())) {
            DocumentType documentType = repository.findByCode(DocumentType.class, DocumentType.CODE_SPECIAL);
            document.setType(documentType);
        } else {
            document.setType(repository.findByCode(DocumentType.class, DocumentType.CODE_OTHER));
        }

        if (AttachmentModel.TYPE_SPECIAL.equals(attachment.getAttachmentType())){
            document.setName(documentType.getName() + " " + getDateAsString());
        } else {
            document.setName("Attachment " + getDateAsString());
        }
    }

This doesn’t compile, because documentType isn’t available in the second block. So, let’s move the declaration of DocumentType outside of the first block.

    public void updateDocument(Attachment attachment){
        Document document = new Document();

        DocumentType documentType = null;
        if (AttachmentModel.TYPE_SPECIAL.equals(attachment.getAttachmentType())) {
            documentType = repository.findByCode(DocumentType.class, DocumentType.CODE_SPECIAL);
            document.setType(documentType);
        } else {
            document.setType(repository.findByCode(DocumentType.class, DocumentType.CODE_OTHER));
        }

        if (AttachmentModel.TYPE_SPECIAL.equals(attachment.getAttachmentType())) {
            document.setName(documentType.getName() + " " + getDateAsString());
        } else {
            document.setName("Attachment " + getDateAsString());
        }
    }

Ah, that’s better. But there’s duplication: document.setType is called on two lines. Let’s move that outside of the if block. And, while we’re at it, let’s do the same for setName.

    public void updateDocument(Attachment attachment){
        Document document = new Document();

        DocumentType documentType = null;
        if (AttachmentModel.TYPE_SPECIAL.equals(attachment.getAttachmentType())) {
            documentType = repository.findByCode(DocumentType.class, DocumentType.CODE_SPECIAL);
        } else {
            documentType = repository.findByCode(DocumentType.class, DocumentType.CODE_OTHER)
        }
        document.setType(documentType);

        String name = null;
        if (AttachmentModel.TYPE_SPECIAL.equals(attachment.getAttachmentType())) {
            name = documentType.getName() + " " + getDateAsString();
        } else {
            name = "Attachment " + getDateAsString();
        }
        document.setName(name);
    }

This is getting in better shape. Now we have separate logic for getting the DocumentType, setting the DocumentType, getting the name, and setting the name. Let’s extract some methods and see what happens.

    public void updateDocument(Attachment attachment){
        Document document = new Document();
        DocumentType documentType = getDocumentType(attachment);
        document.setType(documentType);

        String name = getName(attachment, documentType);
        document.setName(name);
    }

    private DocumentType getDocumentType(Attachment attachment) {
        DocumentType documentType = null;
        if (AttachmentModel.TYPE_SPECIAL.equals(attachment.getAttachmentType())) {
            documentType = repository.findByCode(DocumentType.class, DocumentType.CODE_SPECIAL);
        } else {
            documentType = repository.findByCode(DocumentType.class, DocumentType.CODE_OTHER)
        }
        return documentType;
    }

    private String getName(Attachment attachment, DocumentType documentType) {
        String name = null;
        if (AttachmentModel.TYPE_SPECIAL.equals(attachment.getAttachmentType())) {
            name = documentType.getName() + " " + getDateAsString();
        } else {
            name = "Attachment " + getDateAsString();
        }
        return name;
    }

Our original method looks a lot simpler now. But the methods we’ve extraced contain duplication! The condition itself, the calls to repository.findByCode, and the calls to getDateAsString(). So, let’s fix that.

    public void updateDocument(Attachment attachment){
        Document document = new Document();

        DocumentType documentType = getDocumentType(attachment);
        document.setType(documentType);

        String name = getName(attachment, documentType);
        document.setName(name);
    }

    private DocumentType getDocumentType(Attachment attachment) {
        String documentTypeCode = null; 
        if (isAttachmentTypeSpecial(attachment)) {
            documentTypeCode = DocumentType.CODE_SPECIAL;
        } else {
            documentTypeCode = DocumentType.CODE_OTHER;
        }
        return repository.findByCode(DocumentType.class, documentTypeCode);
    }

    private String getName(Attachment attachment, DocumentType documentType) {
        String name = null;
        if (isAttachmentTypeSpecial(attachment)) {
            name = documentType.getName();
        } else {
            name = "Attachment";
        }
        return name + " " + getDateAsString();
    }

    private boolean isAttachmentTypeSpecial(Attachment attachment) {
        return AttachmentModel.TYPE_SPECIAL.equals(attachment.getAttachmentType());
    }

This code still looks a bit odd. getDocumentType() determines the document type code, and then uses that to find the documentType. And getName() has a similar issue: it determines the prefix for the name, and then appends the date as String.

    public void updateDocument(Attachment attachment){
        Document document = new Document();

        DocumentType documentType = getDocumentType(attachment);
        document.setType(documentType);

        String name = getName(attachment, documentType);
        document.setName(name);
    }

    private DocumentType getDocumentType(Attachment attachment) {
        String documentTypeCode = getDocumentTypeCode(attachment);
        return repository.findByCode(DocumentType.class, documentTypeCode);
    }

    private String getDocumentTypeCode(Attachment attachment) {
        if (isAttachmentTypeSpecial(attachment)) {
            return DocumentType.CODE_SPECIAL;
        } 
        return DocumentType.CODE_OTHER;
    }

    private String getName(Attachment attachment, DocumentType documentType) {
        String name = getNamePrefix(attachment, documentType);
        return name + " " + getDateAsString();
    }

    private String getNamePrefix(Attachment attachment, DocumentType documentType) {
        if (isAttachmentTypeSpecial(attachment)) {
            return documentType.getName();
        } 
        return "Attachment";
    }

    private boolean isAttachmentTypeSpecial(Attachment attachment) {
        return AttachmentModel.TYPE_SPECIAL.equals(attachment.getAttachmentType());
    }

At this point we have some variables and perhaps some methods that are not adding anything in terms of clarity. We should inline them and compact our code a little.

    public void updateDocument(Attachment attachment){
        Document document = new Document();

        DocumentType documentType = getDocumentType(attachment);
        document.setType(documentType);

        document.setName(getName(attachment, documentType));
    }

    private DocumentType getDocumentType(Attachment attachment) {
        return repository.findByCode(DocumentType.class, getDocumentTypeCode(attachment));
    }

    private String getDocumentTypeCode(Attachment attachment) {
        if (isAttachmentTypeSpecial(attachment)) {
            return DocumentType.CODE_SPECIAL;
        }
        return DocumentType.CODE_OTHER;
    }

    private String getName(Attachment attachment, DocumentType documentType) {
        return getNamePrefix(attachment, documentType) + " " + getDateAsString();
    }

    private String getNamePrefix(Attachment attachment, DocumentType documentType) {
        if (isAttachmentTypeSpecial(attachment)) {
            return documentType.getName();
        }
        return "Attachment";
    }

    private boolean isAttachmentTypeSpecial(Attachment attachment) {
        return AttachmentModel.TYPE_SPECIAL.equals(attachment.getAttachmentType());
    }

This refactoring introduced a couple of new methods. Each method call takes a little extra time, and reduces performance a bit. But there’s a catch: with modern processors, cache-misses are the biggest performance killers. Keeping the data as local as possible will reduce cache-misses and increase performance.
In practice, however, I doubt that you’ll even notice the performance difference.

As for clarity, the original code expanded from 11 lines to 34 lines, a 3-fold increase. However, the original method decreased a bit. And because we’ve added a couple of layers of abstraction, the method now communicates only what it does. The details of how are delegated to other methods.

Working with multiple screens in Java

When you want to set the location of a Java Window, you just call setLocation(int x, int y). But what if your screen isn’t big enough? Or when you want to display the window on a second screen?

The desktop is represented by a virtual device, with physical screens providing a viewport onto that device. The top-left corner of the primary screen is always located at coordicates (0, 0). Other physical screens are located relative to this coordinate. See the api-documentation for java.awt.Frame for more information.

To get all available graphics devices, which represent physical screens, use the following code:

GraphicsDevice[] graphicsDevices = 
    GraphicsEnvironment
        .getLocalGraphicsEnvironment()
        .getScreenDevices();

Then, to get the bounds or the offset and size of each device, use the following code:

Rectangle bounds = 
    device
        .getDefaultConfiguration()
        .getBounds();

This works for all screens _except_ the primary screen. The primary screen also contains a taskbar, and you usually don’t want to place a window over the taskbar.

To get the bounds of the primary screen, without the taskbar, use the following code:

GraphicsEnvironment
    .getLocalGraphicsEnvironment()
    .getMaximumWindowBounds();

WAS Deploy Script

When you’re developing for IBM Websphere, you could update your application using the webinterface. But that is a bit slow, and you risk trashing your Websphere installation. You can also use a script. Below is a Windows batch file to do just that.

@setlocal

set WSADMIN_BIN=C:\was_profile\bin
set APP_NAME={My Web Application}
set EAR_LOC=C:\location\application.ear

cd  /D %WSADMIN_BIN%
call wsadmin -c "$AdminApp update %APP_NAME% app {-operation update -contents %EAR_LOC%}"

Installing and using Citrix under Linux Mint

Installing and using citrix under linux might be a bit more tricky than it may appear on first glance. Here are a few steps to make it work.

1. Remove old installation, if needed.

sudo apt-get remove icaclient

2. Download Receiver for Linux. Look for it here: http://www.citrix.com/go/receiver.html
Make sure you have the correct version. This is probably under “For 64-bit Systems”

3. Open the download, and install through package manager.

4. Link certificates:

sudo ln -s /usr/share/ca-certificates/mozilla/* /opt/Citrix/ICAClient/keystore/cacerts

5. in firefox, set Citrix Receiver for Linux plugin to Always Activate.

Troubleshooting Power-Line Communication

Power-Line Communication, turning the power-grid in your home into a computer network, works great! Until it doesn’t. The problem could be that the adapters can find each other, or that the connection is unstable.

Here are some troubleshooting tips that could help with stabilizing the connection:
– Set the network name to some custom name, using the Utilities software which comes with the adapters. Don’t use the default “HomePlugAV”. Check whether there are unknown network adapters which use the name “HomePlugAV” on your network. This could indicate Neighboring Networks Interference.
– Plug the adapter directly into the wall socket. Extension cords degrade the signal.
– Buy adapters with built-in power sockets, and some form of filter. These help to reduce interference even further.

You should see improved performance with these tips

When an application isn’t visible in WebSphere

Every once in a while, WebSphere doesn’t like you. You try to install or update an application, but it refuses to do so, saying the application already exists, and you need to specify a different name. And when you look at the list of your applications, the one you try to install or update isn’t there anymore!

WAS-deployment_error_detailed

Solving this problem isn’t hard, if you know where to look.

1. Shut down the server

2. On the filesystem, remove the application from the following locations:

  • <profile root>/config/cells/<cellname>/applications/<application name>
  • <profile root>/config/cells/<cellname>/blas/<application name>
  • <profile root>/config/cells/<cellname>/cus/<application name>

3. Delete everything from the profile/temp and profile/wstemp directories

4. If needed, edit the following file:
<profile root>/config/cells/<cellname>/nodes/<nodename>/serverindex.xml
Look for the tag <deployedApplications>, and remove your application from there.

5. start the server

You should be able to install your application again.

Sources:
http://www-01.ibm.com/support/docview.wss?uid=swg21590141
http://www.albeesonline.com/blog/2008/04/15/application-already-exists-in-the-configuration-repository-error/

Java: Remove an element from a List

One of the more common tasks in programming is removing a specific element from a list. Although this seems to be straight-forward in Java, it’s a bit more tricky.

Before we start, we should build our list:

   public ArrayList<String> createList(){
      ArrayList<String> myList = new ArrayList<String>();
      
      myList.add("String 1");
      myList.add("String 2");
      myList.add("String 3");
      myList.add("String 4");
      myList.add("String 5");
      
      
      return myList;
   }

Let’s say we want to remove the String “String 2”. The first thing that comes to mind is to loop through the list, until you find the element “String 2”, and remove that element:

   public List<String> removeFromListUsingForEach(List<String> sourceList){
      for(String s : sourceList){
         if (s.equals("String 2")){
            sourceList.remove(s);
         }
      }
      return sourceList;
   }

Unfortunately, in this case, this will throw a

java.util.ConcurrentModificationException

I said “in this case”, because the exception is not always thrown. The details of this strange behavior is out of scope for this blogpost, but can be found here.

There are several ways to remove an element from a list. Depending on your personal preference, and which version of Java you use, here are some examples.

1. Use a for-loop which loops backwards
You can use a for-loop, which runs from the end of the list to the beginning. The reason you want to loop in this direction is, that when you’ve found the element you want to remove, you remove the element at that index. Every element after this one will shift one position towards the beginning of the list. If you’d run the loop forward, you’d have to compensate for this, which just isn’t worth the effort.

   public List<String> removeFromListUsingReversedForLoop(List<String> sourceList){
      for(int i = sourceList.size()-1; i >= 0; i--){
         String s = sourceList.get(i);
         if (s.equals("String 2")){
            sourceList.remove(i);
         }
      }
      return sourceList;
   }

This works in every Java version since 1.2, although you can’t use generics until Java 1.5.

2. Use an Iterator
Another way to remove an element from a list is to use an Iterator. The Iterator will loop through the list, and, if needed, can remove the current element from that list. This is done by calling

Iterator.remove()
   public List<String> removeFromListUsingIterator(List<String> sourceList){
      Iterator<String> iter = sourceList.iterator();
      while (iter.hasNext()){
         if (iter.next().equals("String 2")){
            iter.remove();
         }
      }
      return sourceList;
   }

This works in every Java version since 1.2, although you can’t use generics until Java 1.5.

3. Use Java 8 Streams
What you’re essentially doing here is make a copy of the list, and filter out the unwanted elements.

   public List<String> removeFromListUsingStream(List<String> sourceList){
      List<String> targetList = sourceList.stream()
            .filter(s -> !s.equals("String 2"))
            .collect(Collectors.toList());
      return targetList;
   }

This works since Java 1.8. More about Java 8 can be found here.

Distributed Websearch

When it comes to searching the web, the first thing that comes to mind is Google. Or Bing. Or Yahoo. Sure, it’s easy, fast, and sort of reliable. However, there are a few problems with these kinds of services.

First of all, there’s the filter bubble. These search engines (and social networks) will present results that are specifically tailored for you. On the one hand, this is a good thing, because you’ll probably find what you’re looking for faster. However, you’ll never find information that COULD be relevant, but is filtered out for you. Your world view is being limited by this filter bubble.

You can work around this by using “anonymous” search engines, such as DuckDuckGo or Startpage. These search engines don’t store your personal data, and therefore can not create a filter bubble for you. As for Startpage, that search engine will act as a proxy between you and Google. You will usually get high quality results to your search query.

Another problem is “The Right To Be Forgotten”. The European court ruled that Google needs to provide the option to delete certain search results from its index. When you’ve had problems, which have been resolved, you shouldn’t be judged on the basis of those past problems. However, once information is on the Internet, it’s very hard to remove. The toothpaste is out of the tube, the genie out of the bottle. You’ll never get it back in. Google provides links to this information, it does not provide the information itself. Removing the links is not the same as removing the information. We have seen the same misunderstanding in the case of The Pirate Bay.

YaCy

Since a couple of years, there is YaCy. YaCy is a distributed search engine, that ensures TRUE anonimity, and is impossible to take down. You need to install a piece of software on your computer, browse to the local webserver (probably http://localhost:8090/), and start searching. At this moment, there are 1.7 billion documents in the public network. In contrast, the web is estimated to contain 15 to 55 billion documents.

There are a couple of other interesting features in YaCy, such as creating a search engine for one specific topic, or a search engine for your local intranet. Give it a try.

The Pomodoro Technique

One of my favorite time management methods is the Pomodoro Technique. The method is basically as follows:

  1. Pick a task.
  2. Work on it for 25 minutes. This is called a Pomodoro.
  3. Take a 5 minute break. Do something totally unrelated to your work.
  4. Work for another Pomodoro, or 25 minutes. This can be on the same task, or a new one if the previous one is finished.
  5. After 4 Pomodoros, take a longer break of 15 to 30 minutes.

Because of the breaks, your mind gets just enough rest to stay focussed. Also, because you’re supposed to work on one task, and one task only during your Pomodoro, the quality of your work can go up.

Ofcourse, the technique is completely customizable. Do you think 25 minutes is too short (or too long)? Try 45 minutes (or 10 minutes). Do you need a long break sooner? Do it every 3 Pomodoros.

No I’ve made my own Pomodoro tracker. It’s written in Java 8, and it’s open source. You can find the source here . A runnable version can be found here.

This is still work in progress, and I mainly made it as a challenge to myself. If you like it, do whatever you want with it.

The pomodoro is running!
The pomodoro is running!

When the screen and the tray icon are red, a pomodoro is running. Right clicking the tray icon will bring up a menu.

Pomodoro break.
Pomodoro break.

When the screen and the tray icon are green, you are on a break.

Waiting for the next Pomodoro to be started.
Waiting for the next Pomodoro to be started.

When the screen and the tray icon are blue, the program is waiting.

Changing the settings
Changing the settings

The settings allow you to specify the location of the program, the times and the number of Pomodoros between long breaks.