2014-01-13

Properties from maven

Introduction

Sometimes your code should work in many environments using varaibles defined in many places. There could be default variable in code (when configuration is not defined), variable in configuration file or pom.xml for tests and maybe each developer should have own variable value...

Property reader code

All examples will be tests and will be use PropertyReader class which is defined below.
package com.blogspot.przybyszd.sandbox.propertyplaceholders;

import java.util.Properties;

public class PropertyReader{
    
    public static Properties readProperties(final String configurationFile){
        Properties properties = new Properties();
        try{
            properties.load(PropertyReader.class.getResourceAsStream(configurationFile));
        }catch(Exception e){
            System.err.println("Configuration file was not found");
        }
        return properties;
    }   
}
All properties files will be defined in src/test/resources.

Default properties in code

First, assume that properties file is not provided or property is not given:
package com.blogspot.przybyszd.sandbox.propertyplaceholders;

import static org.junit.Assert.assertEquals;
import java.util.Properties;
import org.junit.Test;

public class PropertyReaderTest{
    
    @Test
    public void shouldUseDefaultPropertyFromCode(){
        // given
        Properties properties = PropertyReader.readProperties("/no-existing-file.properties");
        // when
        String value = properties.getProperty("address", "localhost");
        // then
        assertEquals("localhost", value);
    }
}
But when property file exists and has this property then it will be used:
@Test
public void shouldUsePropertyFromFile(){
    // given
    Properties properties = PropertyReader.readProperties("/existing-file.properties");
    // when
    String value = properties.getProperty("address", "localhost");
    // then
    assertEquals("10.10.10.10", value);
}
Property in file existing-file.properties:
address=10.10.10.10

Default properties in pom.xml

Properties could be also defined in pom.xml and then placeholders could be used in property file. Test is going first:
@Test
public void shouldUsePropertyFromPom(){
    // given
    Properties properties = PropertyReader.readProperties("/file-with-placeholder.properties");
    // when
    String value = properties.getProperty("address", "localhost");
    // then
    assertEquals("trololo.com", value);
}
Instead of value in properties file there is only placeholder (file file-with-placeholder.properties):
address=${address}

Value of property is defined in pom.xml (filtering of test resources must be set to true and, optionally, resource filtering could be set to true):
<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>property-placeholders</groupId>
 <artifactId>property-placeholders</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <name>PropertyPlaceholder</name>

 <properties>
  <address>google.com</address>
 </properties>

 <build>
  <resources>
   <resource>
    <directory>src/main/resources</directory>
    <filtering>true</filtering>
   </resource>
  </resources>
  <testResources>
   <testResource>
    <directory>src/test/resources</directory>
    <filtering>true</filtering>
   </testResource>
  </testResources>
 </build>

 <dependencies>
  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>4.11</version>
   <scope>test</scope>
  </dependency>
 </dependencies>
</project>
Now variable could be also set from command line:
mvn -Daddress=my-address clean test

Default property in settings.xml

Each developer (or each environment) could define some properties in settings.xml in $HOME/.m2 directory and these properties overwrite properties defined in pom.xml.
Test first:
@Test
public void shouldUsePropertyFromSettingsXMl(){
    // given
    Properties properties = PropertyReader.readProperties("/file-with-placeholder.properties");
    // when
    String value = properties.getProperty("address2", "localhost");
    // then
    assertEquals("yahoo.com", value);
}
I add new property address2 so I have to add property placeholder in properties file and in pom.xml.
Properties file:
address=${address}
address2=${address2}
pom.xml:
<properties>
 <address>google.com</address>
 <address2>bing.com</address2>
</properties>
And now variable address2 will be redefined in settings.xml file :
<settings>
  <profiles>
    <profile>
      <id>property-placeholder</id>
      <activation>
        <activeByDefault>true</activeByDefault>
      </activation>
      <properties>
        <address2>yahoo.com</address2>
      </properties>
    </profile>
  </profiles>
</settings>
This profile is active by default so there is not need to use -P parameter.
Not the tests pass.

Conclusion

Use Maven and define properties anywhere.

2014-01-11

Try catch with resources

Introduction

Today I would like to describe a try catch with resource, which is available in Java 7. Additional I show template for Eclipse, which generate such try-resource for reading file.


Try catch in Java 6

In Java 6 (or earlier) you have to write try catch like this:
BufferedReader bin = null;
try{
    bin = new BufferedReader(new FileReader("trolo.txt"));
    String line = null;
    while((line = bin.readLine()) != null){
        // parse line
    }
}catch(IOException e){
    LOG.error("IO exception when creating reader or reading", e);
    throw new MyException(e);
}finally{
    try{
        if(bin != null){
            bin.close();
        }
    }catch(IOException e){
        LOG.error("IO exception when closing", e);
        throw new MyException(e);
    }
}

It is not quite nice... You have to declare BufferedReader before try block and close it in finally (of course if it is not null). Additionally close method could throw IOException which should be handle...

Try catch with resource in Java 7

Java 7 came to us with resources for try. Each resource have to implement interface AutoClosable. It has only one method: close, which is called at the end of try catch with resource. Ant this is an example of use:
try (BufferedReader bin = new BufferedReader(new FileReader("trolo"))){
    String line = null;
    while((line = bin.readLine()) != null){
        // parse line
    }
}catch(IOException e){
    LOG.error("IO exception", e);
    throw new MyException(e);
}
Shorter? Creating, reading or closing BufferedReader could throw exception so we still need catching of IOException, but only once. Finally block is ommited.

Eclipse template

In Eclipse you could define a template, which insert try catch with resource and you job is only name the variables and give file name. I was inspired by this post, to write this template.
${:import(java.io.BufferedReader, java.io.FileReader, java.io.Exception)}
try(BufferedReader ${buffName} = new BufferedReader(new FileReader(${fileName}))){
 String ${line} = null;
 while((${line} = ${buffName}.readLine()) != null) {
        ${cursor}
 }
}catch(IOException e){
    // TODO Auto-generated stub
    throw new UnsupportedOperationException("Not implemented yet");
}

Conclusion

Java 7 came with big improvement for try catch. Now is is shorter to use in try any resource which have to be closed at the end.

2014-01-04

Eclipse configuration for Java

Introduction

Eclipse is an great IDE, but only with some plugins (or only one) and changes in default settings. I show you how to prepare the best in my opinion environment to developing in Java with TDD style.

Settings

First open Window menu and select preferences. There you have some interesting settings.

Java -> Appearance -> Type filters

Add here class java.lang.Object to not see methods of Object class: equals, wait, notify etc. Add also package java.awt. Always annoys me when i have to import java.util.List but first class List is derived from java.awt.

Java -> Code style

Exception variable name is set to e and option 'Add @Override annotation for new overriding methods' is set.

Java -> Code style -> Clean Up

Eclipse could perform some tasks when you clean up your code from source menu. Create new profile and set:
  1. In first tab (Code Organizing): 
    • Format source code
    • Organize imports
  2. In Code Style tab:
    • Use blocks in if/while/for/do statements -> Always (because when you add code to your if body you could forget to put it into block)
    • Convert 'for' loops to enhanced
    • Use modifier 'final' where possible (select only parameters, because when you assign variable to parameter it is code smell and this protects you from doing bad things) 
  3. In Member Accesses tab:
    • Use declaring class as qualifier (select only access through instance and subtypes)
  4. In Missing Code tab:
    • Add missing annotations: @Override, @Override when implementation of method from interface and @Deprecated
    • Add serial version ID (generated)
    • Add unimplemented method (body will be taken from code template)
  5. In Unnecessary Code tab:
    • Remove unused imports
    • Remove unnecessary casts
    • Remove unnecessary '$NON-NLS$' tags

Java -> Code style -> Code templates

Method, constructor and catchblock body will be change to throw exception when is generated. When you forget to implement method or block you obtain UnsupportedOperationException.
Set method and catch block body to:
// ${todo} Auto-generated catch block
throw new UnsupportedOperationException("Not implemented yet");
Set constructor body to:
${body_statement}
// ${todo} Auto-generated constructor stub
throw new UnsupportedOperationException("Not implemented yet");

Java -> Code style -> Formatter

This options helps me read code and I just like this form of code. The same defined formatter rules should be used by all team members, so you could export configuration and give to your team mates.
  1. In tab Indentation:
    • Declarations within class body
    • Declarations within enum body
    • Declarations within class constants
    • Declarations within annotation body
    • Statements within method/constructor body
    • Statements within blocks
    • Statements within 'switch' body
    • Statements within 'case' body
    • 'break' statements
    • Empty lines
  2. In tab Braces:
    • All options set to 'Same line'
  3. In tab White Space:
    • Declarations:
      • Classes: after comma in implemented clause
      • Fields: after comma in multiple field declarations
      • Constructors: after comma in parameters and after comma in 'throws' clause
      • Methods: after comma in parameters, before ellipsis in vararg parameters, after ellipsis in vararg parameters and after comma in 'throws' clause
      • Labels: after colon
      • Annotations: after comma
      • Enum types: after comma between constants and after comma in constant arguments
    • Control statements:
      • 'for': after comma in initialization, after comma in increments, after semicolon, befor colon and after colon
      • 'try-with-resources': before opening parenthesis and after semicolon
      • 'assert': before colon and after colon
      • 'return': before parenthesized expressions
      • 'throw': before parenthesized expressions
    • Expressions:
      • Function invocations: after comma in methods arguments, after comma in object allocation arguments and after comma in in explicit constructor call
      • Assignments: before assignment operation and after assignment operation
      • Operators before binary operations and after binary operations
      • Type casts: after closing parenthesis
      • Conditionals: before question mark, after question mark, before colon and after colon
    • Arrays:
      • Arrays initializers: after comma
    • Parameterized types:
      • Type reference: after comma
      • Type arguments: after comma
      • Type parameters: after comma in parameters, before '&' in type bounds and after '&' in type bounds
  4. In tab Blank Lines:
    • 0 blank lines before package declaration, before first declaration, before field declarations and at begining of method body
    • 1 otherwise
  5. In tab New Lines:
    • after labels
    • at end of files
    • put empty statements on new line
    • insert new line after annotations on package
    • insert new line after annotations on types
    • insert new line after annotations on fields
    • insert new line after annotations on methods
    • insert new line after annotations on local variables
  6. In tab Control Statements:
    • Keep 'else if' on one line
  7. In tab Line Wrapping:
    • Prefer wrapping outer expressions (keep nestedexpression in one line)
    • Annotations: wrap all elements, every element on a new line
    • Class declarations: Do not wrap
    • Constructor declarations: Do not wrap
    • Method declarations: Do not wrap
    • 'enum' declarations: wrap all elements, every element on a new line
    • Function calls: Do not wrap
    • Expressions: Do not wrap
    • Statements:
      • Compact 'if else' and 'multi-catch': Do not wrap
      • 'try-with-resource': Wrap all elements, except first element if not necessary (additionally set indentation policy to Indent on column)
  8. In tab Comments:
    • Enable Javadoc comment formatting
    • Enable block comment formatting
    • Enable line comment formatting
    • Format line comments on first column
    • Enable header comment formatting
    • Never join lines
    • Format HTML tags
    • Format Java code snippets inside 'pre' tags
    • Indent Javadoc tags
    • /** and */ after separate lines
    • Remove blank lines
    • /* and */ after separate lines
    • Remove blank lines
    • Maximumline width for comments: 200
  9. Off/On Tags (Disable formatting between some comments):
    • Enable Off/On tags
    • Off tag: DO NOT INDENT
    • On tag: NOW INDENT

Java -> Code style -> Organize Imports

Set only number of import and static import needed for * to 100. I do not like imports with * when I am using IDE.

Java -> Compiller -> Building

There are problems which could occur with whole project.
  1. General
    • Enable use of exclusion patterns in source folders 
    • Enable use of multiple output locationsfor source folders
  2. Build path problems 
    • warnings on Incompatible required libraries and No strictly compatible JRE for execution environment available
    • errors otherwise
  3. Output folder
    • warning when duplicated resource
    • I scrub output folders when cleaning projects

Java -> Compiller -> Error/Warnings

There are problems which could occurs in code.
  1. Code style
    • warning on:
      • Non-static access to static member
      • Access to non-accessiblemember of enclosing type
      • Parameter assignment
      • Method with a constructor name
    • ignore otherwise
  2. Potential programming problems
    • error on:
      • Possible accidentalboolean assignment
      • Dead code
    • warning on:
      • Comparing identical values
      • Assignment has no effect
      • Using a char arrayin string concatenation
      • Inexact type match for varargs arguments
      • Empty statement
      • Unused object allocation
      • Incomplete 'switch' case on enum
      • Hidden catch block
      • 'finally' does not complete normally
      • Resource leak
      • Seralizable class without serialVersionID
      • Missing synchronization modifier on inherited method
      • Class overides 'equals()' but not 'hashCode()'
    • ignore otherwise
  3. Name shadowing and conflicts
    • warning on:
      • Type parameter hides another type
      • Method does not override package visible method
      • Interface method conflicts with protected 'Object' method
    • ignore otherwise
  4. Deprecated and restricted API
    • error on forbidden reference
    • warning on:
      • Deprecated API (both options checked)
      • Discourage reference
  5. Unnecessary code: all options set to warnings and selected 'Ignore in overriding and implementing methods' boxes
  6. Generic types: all options set to warnings and selected 'Ignore unavoidable generic type problems'
  7. Annotations: all options set to warnings and selected 'Include implementations of interface methods' and 'Enable @SuppressWarnings annotations' boxes
  8. Null analysis
    • warning on null pointer access
    • ignore otherwise

Java -> Compiller -> Javadoc

There are problems which could occurs in javadoc comments.
Select 'Process Javadoc comments'. Set warning on malformed Javadoc comments, but only on public members and then validate tag arguments, report non visible references, deprecated references and validate all standard tags missing description.
When tag is missing then warning should apear but only on public members, ignoring overriding and implementing methods and method type parameters.
Ignore missing Javadoc comments. Why? Because you do not need javadoc, but when you do then you should have valid comments.

Java -> Editor -> Content Assist

This options are used when CTRL+Space are pressed. I have set:
  1. Insertion
    • Completion inserts
    • Insert single proposals automatically
    • Add import instead of qualified name
    • Use static imports
    • Fill method arguments and show guessed arguments
    • Insert best guessed arguments (It really could quess what you think)
  2. Sorting and filtering
    • Sort proposals by revelance
    • Show camel case matches
    • Hide proposals not visible in the invocation context
  3. AutoActivation should be enable and activate after 200 ms or on . (dot) sign.

Java -> Editor -> Content Assist -> Advanced

Choose only these proposals which you will be use. I suggest to add templete and word proposals and set them at the beggining of content assist cycle.

Java -> Editor -> Content Assist -> Favourites

There you can set static methods, static fields or classes for quick proposals. It is extremely useful for tests. I have here:
  1. Static members from:
    • com.googlecode.catchexception.CatchException
    • org.fest.assertions.Assertions
    • org.hamcrest.CoreMatchers
    • org.hamcrest.Matchers
    • org.junit.Assert
    • org.junit.Assume
    • org.junit.matchers.JUnitMatchers
    • org.mockito.Matchers
    • org.mockito.Mockito
  2. Classes from package:
    • org.junit

Java -> Editor -> Save Actions

I have set all options like in clean up.

Java -> Editor -> Templates

I use many templates written on my own. There are some or them:
  1. after: method which have to be invoke after each JUnit test:
    ${:import (org.junit.After)}
    @After
    public void tearDown() {
        ${cursor}
    }
  2. before: method which have to be invoke before each JUnit test:
    ${:import(org.junit.Before)} 
    @Before
    public void prepareTest() {
     sut = new ${cursor} 
    }
  3. indent-off: when I do not want to have formatted code, for example when using long invocations in fluent API:
    // DO NOT INDENT
    
    //NOW INDENT
  4. logger: add log4j logger static member:
    private static final Logger LOG = LoggerFactory.getLogger(${enclosing_type}.class); ${imp:import(org.slf4j.Logger)} ${i:import(org.slf4j.LoggerFactory)}
  5. test: add JUnit test template:
    @${testType:newType(org.junit.Test)}
    public void should${cursor}() {
     //given
     
     //when
     
     //then
     fail(); ${staticImport:importStatic('org.junit.Assert.*','org.mockito.Mockito.*')} 
    }

Java -> Editor -> Typing

    Select all options. Everything is perfect.

    Plugins

    In fact, you need only one powerful plugin named MoreUnit. Additionally, when you start programming in TDD you could find useful plugin Pulse.

    MoreUnit

    Great plugin, which enable jumping between class implementation and tests using shortcuts:
    • CTRL+R - run tests for classes
    • CTRL+J - jump to test/implementation or create test class if not exist
    MoreUnit requires a few settings to work perfectly. Open Window menu, select Preferences and MoreUnit. In Java subpreferences set test source folder as src/test/java (when you use Maven). 
    I have unit and integration tests and I recognize them by suffix of test class name: unit test class ends with word Test and integration tests ends with IT, so as rule for MoreUnit I have set pattern '${srcFile}(Test|IT)' (the same pattern should be set in User Language subpreferences of MoreUnit).  Additionally, all test methods have content 'throw new RuntimeException("not yet implemented");' and I have enabledextended search for test methods, so that I can jump also between method implementation and tests using this method.

    Pulse

    It is simple plugin, which you have to start in pulse view and you could observe your 'TDD pulse' i.e. red (write failing test) -> green (make test pass by implementing class) -> refactor (implementation of class and test class) -> red -> ... as if it was hearbeats.

    Conclusion

    Eclipse is very powerful IDE. But when you download it, it requires some additional settings and, as you can see, one or two plugins to work perfectly and highly support programmer work.