Java EE 6 Testing with Arquillian Persistence Extension

Posted by admin | Posted in General Programming, Learning Materials, Tools | Posted on 22-12-2011

2

Today I will describe my newly discovered library which is an extension to the great JBoss Arquillian project.

The mission of the Arquillian project is to provide a simple test harness that abstracts away all container lifecycle and deployment from the test logic so developers can easily produce a broad range of integration tests for their enterprise Java applications.

Arquillian persistence extension allows you to test JPA related code without filling up the database with test data. All you have to do is to populate .yml file with your data specified. That will be best described with an example.

First of all add arquillian persistence dependencies to your project:

<dependency>
            <groupId>org.jboss.arquillian.extension</groupId>
            <artifactId>arquillian-persistence-api</artifactId>
            <version>${version.arquillian_persistence}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.arquillian.extension</groupId>
            <artifactId>arquillian-persistence-impl</artifactId>
            <version>${version.arquillian_persistence}</version>
            <scope>test</scope>
        </dependency>

where ‘${version.arquillian_persistence}’ is equal to ’1.0.0.Alpha2′. I assume that you have the basic arquillian tests (for EJB’s and CDI) working, If not read on.

I have found myself setting up arquillian enabled project quite cumbersome, always ending up with some classpath dependency problems while trying to remote test my classes. For those of you new to Arquillian I would strongly recommend starting up with working example provided by Bartosz Majsak and available on github as a ‘Beer-Advisor‘ project.

The ‘Beer-Advisor’ project can be quickly refactored to suit your needs, it lack comments but its so clearly written that it shouldn’t be a problem to grasp the idea.

Ok then, lets get going with the arquillian persistence extension, we are going to use two nice annotations to help us testing our JPA layer: @UsingDataSet and @ShouldMatchDataSet.

We start off with doing some setup, I will copy part of the example from the Beer-Advisor project which you can easily clone and try for yourself:

Having an entity class Beer:

@Entity
public class Beer implements Serializable
{
   private static final long serialVersionUID = 5892013208071126314L;

   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   private Long id;

   @Basic
   private String name;

   @Basic
   private BigDecimal price;

   @Basic
   private BigDecimal alcohol;

   @Basic
   private String code;

   @Enumerated(EnumType.STRING)
   private Type type;

   // If lazy then Glassfish Embedded is facing this problem: https://bugs.eclipse.org/bugs/show_bug.cgi?id=323403
   @ManyToOne(optional = false, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
   private Brewery brewery;

   Beer()
   {
      // to satisfy JPA
   }

   public Beer(Brewery brewery, Type type, String name, BigDecimal price, BigDecimal alcohol)
   {
      this.name = name;
      this.price = price;
      this.alcohol = alcohol;
      this.type = type;
      this.brewery = brewery;
      this.brewery.addBeer(this);
   }
........ Getters and Setters ...............

and simple DAO for managing Beer objects on the persistence layer:

@RequestScoped
public class JpaBeerRepository implements BeerRepository
{
   @PersistenceContext
   private EntityManager em;

   @Override
   public Beer getById(Long id)
   {
      return em.find(Beer.class, id);
   }
..........

@Override
   public Set<Beer> fetchAll()
   {
      CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
      CriteriaQuery<Beer> query = criteriaBuilder.createQuery(Beer.class);
      Root<Beer> from = query.from(Beer.class);
      CriteriaQuery<Beer> select = query.select(from);

      Set<Beer> result = new HashSet<Beer>();
      result.addAll(em.createQuery(select).getResultList());

      return result;
   }

   @Override
   public void save(Beer beer)
   {
      if (beer.getId() == null)
      {
         em.persist(beer);
      }
      else
      {
         em.merge(beer);
      }
   }
..................

We can easily test our DAO by creating datasets in yml format and test our logic against it:

Beer:
  - id: 1
    alcohol: 4.5
    name: "Mocny Full"
    price: 1.0
    type: LAGER
    brewery_id: 1
  - id: 2
    alcohol: 55.0
    name: "End of history"
    price: 765
    type: BLOND_ALE
    brewery_id: 2
  - id: 3
    alcohol: 41.0
    name: "Sink The Bismarck!"
    price: 64.0
    type: QUADRUPEL_IPA
    brewery_id: 2
  - id: 4
    alcohol: 8.5
    name: "Delirium Tremens"
    price: 10.0
    type: PALE_ALE
    brewery_id: 3
  - id: 5
    alcohol: 8.4
    name: "Pauwel Kwak"
    price: 4.0
    type: AMBER
    brewery_id: 4

You should put your .yml file into test/resources/datasets folder in you maven project

@UsingDataSet annotation will populate our database with the data specified in beers.yml file

   @Test
   @UsingDataSet("beers.yml")
   public void shouldReturnBeerByItsId() throws Exception
   {
      // given
      Long beerId = 1L;
      String expectedName = "Mocny Full";

      // when
      Beer beers = beerRepository.getById(beerId);

      // then
      assertThat(beers.getName()).isEqualTo(expectedName);
   }

Now, lets say we want to add new Beer and see if the database will have a specific data in it, for this purpose we are going to use @ShouldMatchDataSet(..)

@Test
    @ShouldMatchDataSet("expected-insert-beer.yml")
    public void shouldSaveNewBeer() throws Exception{
        //when
        Beer b = new Beer();
                //set the necessary fields on the beer object
        beerRepository.save(b);
        assertThat(beerRepository).isNotNull();
    }

after inserting our Beer object to the database through the EntityManager we should end up with a single beer record in our database, exactly like the one specified in ‘expected-insert-beer.yml’.

Why you should join Stackoverflow

Posted by admin | Posted in General Programming, Learning Materials | Posted on 04-10-2011

0

Back in May 2008 when I first heard about stackoverflow idea I was really skeptical about it. You can read my rants about the whole idea here. Since then, I have used stackoverflow more and more and I have to say that for the last couple of months I actually love it.This was a long process for me but I can assure you, that this post is going to be completely different the the one written in the middle of 2008.
Once I started contributing and become a part of stackoverflow community I have discovered quite a few things about me and about the website itself.

I think many developers agree, that if you are into programming you are willing to learn all the time, learning is fun and if you have a source of learning repeatedly every day something new, you will be a happy developer. Of course many of us read books, blogs, community sites like reddit, dzone or digg, looking for something cool to read every day. Many of us do certifications just for fun, just to get some feeling of knowledge gaining. For me Stackoverflow is becoming one of the major sources of self development which I can do at my own peace.

Possibly, every person will find something different for himself at stackoverflow, and it all depends on our personal preferences and goals. If you are reading this and you still don’t use stackoverflow much, I urge you to try at least for a month.

1. You can learn by teaching


Everyone who has ever thought about improving his own learning efficiency knows this. When you try to teach what you have just learned, everything auto-magically get nicely organized in your head. All you have to do is to find a way to share your knowledge – now you can, use a stackoverflow of course.

You can read more about effective learning here.

2. You can collect stuff



Turbo bubble gum pictures by KnightRiderDDR


The first and last thing in my life I was actually collecting, was a chewing gum stickers in the middle eighties, they were called ‘Turbo’ and most of the people reading this won’t probably know them, as they were sold in eastern europe only(I can be wrong), it was fun though, but now I have stackoverflow :) .
For all the people collecting all kind of stuff, well, by using a stackoverflow you can fullfill your desire and collect something new – stackoverflow points and different kinds of badges

3. You can compete

People like competition of many kinds and they do it for whatever reason. Whatever reason you have, you can now compete on stackoverflow when providing better answers than others, collecting more points etc.
Remember, competition is a driving force of progress.

4. You can revise your knowledge

This is for me actually the most important point. Remember “forgetting curve”? No? Well, its because you have probably not revised that information and you have forgotten :)
This is simple, if you don’t repeat what you have learned you will finally forget it. By using a stackoverflow you can highly minimize or prevent totally your memory loss.

Forgetting Curve - Wikipedia

5. You can expand your knowledge

If you’ll jump into a stackoverflow mania you will spend there a bit more time than just the time answering/asking questions. You will probably be browsing the web app, reading notification of posted comments to your questions/answers, at the same time you notice other people answers, you’ll often find out a better approach of doing something than your own answer gave, links to an on-line articles, documentation, other interesting questions in your field of expertise etc, you’ll just find the best of the web posted by other people in one place, all related to whats the most interesting for you.

6. You can ask questions yourself

I almost forgot about this one. You can of course ask questions there and if they are not too difficult someone will probably answer them pretty fast :)

7. You can join Careers 2.0

I’ve just joined Careers 2.0 and I can say that it’s well done web app, unfortunately there is not a single company from Poland :) . Anyway I guess it can be useful for others (especially in the US + UK state)

8. You can meet people at Stackoverflow meet-up days



Haven’t tried that yet but It’s always good to have a good excuse to go for a beer, or isn’t it?

Installing Artifactory on Ubuntu box

Posted by admin | Posted in General Programming, Tools | Posted on 25-02-2011

2

This is a simple and straightforward guide on how to install Artifactory and import exisiting maven repository into it.

1. Download Artifactory from JFrog website
2. Unzip downloaded file in your home directory
3. Change to root user (su -)
4. Set your JAVA_HOME in /etc/environment

JAVA_HOME=/usr/lib/jvm/java-6-sun/
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games"

5. Set your JAVA_HOME in /etc/profile

# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).
export JAVA_HOME=/usr/lib/jvm/java-6-sun/
if [ -d /etc/profile.d ]; then
  for i in /etc/profile.d/*.sh; do
   .............. rest of the file.....

6. Go to /home/kris/artifactory-2.3.2/bin (of course replace ‘kris’ with your home folder name)
7. Run

$: ./install.sh

8. Check if your installation was successful, run:

$: service artifactory check

9. If you get error saying something like: “Cannot find a JRE or JDK. Please set JAVA_HOME to a >=1.5 JRE” , edit /etc/artifactory/default and add JAVA_HOME export:

10. Run the check again (service artifactory check) and if all goes fine run

[cc lang="bash"]
$: service artifactory start

11. In your browser to into: http://localhost:8081/artifactory and log in as administrator (default user/pass is admin/password)

12. After logging in, click on the ‘Admin’ tab, then ‘Import & Export’ and ‘Repositories’

13. Inside the ‘Import’ section select ‘ext-release-local’ as your ‘Target Local Repo’ and find your maven .m2 repository

14. Click import and your are all set!

Design Patterns Series – Part Five: Adapter pattern

Posted by admin | Posted in Code Snippets, General Programming | Posted on 04-02-2011

1

According to wikipedia:

In computer programming, the adapter pattern (often referred to as the wrapper pattern or simply a wrapper) is a design pattern that translates one interface for a class into a compatible interface.

The adapter pattern is commonly used when there is a need to access an object through the interface which doesn’t match the one you need. This pattern is especially useful if you have a set of existing classes and you need to use them together with other ones, exposing different interface.


The purpose of this pattern is to make some objects look like something they are not. Normally, you wouldn’t use this pattern at the design stage but rather while extending an existing application, working with 3rd party libraries or tools.

Simple example using adapter pattern:
We have an existing class called ThirdPartyShape with a method ‘paintShape’ we want to move into a common interface.

package adapterpattern;

/**
 *
 * @author kris
 */

public class ThirdPartyShape {

    public void paintShape(){
        System.out.println("Painting 3rd party shape");
    }
}

Common interface in our new application:

package adapterpattern;

/**
 *
 * @author kris
 */

public interface ShinyShapeIfc {

    public void paint();
}

Example of standard shape class in our application:

package adapterpattern;

/**
 *
 * @author kris
 */

public class MyNewShinyShape implements ShinyShapeIfc{

    public void paint(){
        System.out.println("Painting brand new and shiny custom shape!");
    }
}

Adapter class used to utilize functionality of 3rd party class into our interface for painting shapes

package adapterpattern;

/**
 *
 * @author kris
 */

public class ShinyShape3rdpartyAdapter implements ShinyShapeIfc{

    private ThirdPartyShape thirdPartyShape;

    public ShinyShape3rdpartyAdapter(ThirdPartyShape tps){
        this.thirdPartyShape = tps;
    }
    /**
     * Method adapting 3rd party functionality into a common
     * interface
     */

    public void paint() {
        this.thirdPartyShape.paintShape();
    }

}

Simple proof of concept, using our shapes with existing 3rd party shapes by implementing and adapter pattern:

/**
 *
 * @author kris
 */

public class Main {

    /**
     * @param args the command line arguments
     */

    public static void main(String[] args) {
        ThirdPartyShape thirdPartyShape = new ThirdPartyShape();
        ShinyShapeIfc myOwnShinyShape = new MyNewShinyShape();
        //adapting 3rd party class into a common interface using an adapter
        ShinyShapeIfc adapted3rdPartyShape = new ShinyShape3rdpartyAdapter(thirdPartyShape);

        //object below implement common interface
        myOwnShinyShape.paint();
        adapted3rdPartyShape.paint();
    }

}

Design Pattern Series – Part Four: Observer pattern

Posted by admin | Posted in Code Snippets, General Programming | Posted on 02-02-2011

0

Today I’m adding another important design pattern to the toolbox. Observer Pattern is commonly used and quite powerful.

The Observer Pattern defines one to many dependency between objects so that when one object changes state, all of it dependents are notified and updated.

We can create a class structure for the pattern ourselves from scratch or we can use build in Observer functionality in JDK.

Utilizing JDK Observer-Observable mechanism:

NameService.java

package jdk_observerpattern;

import java.util.Observable;

/**
 *
 * @author kris
 */

public class NameService extends Observable {

    private String name;

   
    public String getName() {
        return name;
    }

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


}

NameObserver.java

package jdk_observerpattern;

import java.util.Observable;
import java.util.Observer;

/**
 *
 * @author kris
 */

public class NameObserver implements Observer{

    private final String objName;

    public NameObserver(String observername){
        this.objName = observername;
    }
    public void update(Observable o, Object o1) {
        System.out.println("Observer: " + this.toString() + ", name changed: " + o1);
    }

    @Override
    public String toString() {
        return this.objName;
    }


}

Main method for testing:

package jdk_observerpattern;

/**
 *
 * @author kris
 */

public class Main {

    private NameService service;
    private NameObserver observer1;
    private NameObserver observer2;

    public Main(){
        service = new NameService();
        observer1 = new NameObserver("First Observer");
        observer2 = new NameObserver("Second Observer");
        service.addObserver(observer1);
        service.addObserver(observer2);
    }
    /**
     * @param args the command line arguments
     */

    public static void main(String[] args) {
        Main m = new Main();
        m.test();
    }
    public void test(){
       
        System.out.println("Count: " + service.countObservers());
        service.setName("Big Lebowsky");
        System.out.println(service.getName());

    }

}

Custom Observer pattern implementation:

Subject interface

package custom_observerpattern;

/**
 *
 * @author kris
 */

public interface Subject {
    public void registerObserver(Observer o);
    public void removeObserver(Observer o);
    public void notifyObservers(Object obj);
}

Observer interface:

package custom_observerpattern;

/**
 *
 * @author kris
 */

public interface Observer {
    public void updateStatus(Object o);
}

NameService:

package custom_observerpattern;

import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author kris
 */

public class NameService implements Subject {

    private List<Observer> observers;
    private String name;

    public NameService(){
        observers = new ArrayList<Observer>();
    }
    public void registerObserver(Observer o) {
        this.observers.add(o);
    }

    public void removeObserver(Observer o) {
        this.observers.remove(o);
    }

    public void notifyObservers(Object obj) {
        for(Observer o : this.observers){
            o.updateStatus(obj);
        }
    }

    public String getName() {
        return name;
    }

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

}

NameObserver:

package custom_observerpattern;

/**
 *
 * @author kris
 */

public class NameObserver implements Observer {

    private final String objName;

    public NameObserver(String observername){
        this.objName = observername;
    }
    public void updateStatus(Object o) {
        System.out.println("Updating status: " + o);
    }
    @Override
    public String toString() {
        return this.objName;
    }

}

Main class for testing purposes:

package custom_observerpattern;

/**
 *
 * @author kris
 */

public class Main2 {

    private NameService service;
    private NameObserver observer1;
    private NameObserver observer2;

    public Main2() {
        service = new NameService();
        observer1 = new NameObserver("First Observer");
        observer2 = new NameObserver("Second Observer");
        service.registerObserver(observer1);
        service.registerObserver(observer2);
    }

    public static void main(String[] art) {
        Main2 m = new Main2();
        m.test();
    }

    public void test() {
        service.setName("Big Lebowsky");
        System.out.println(service.getName());

    }
}

The Biggest Java WTF

Posted by admin | Posted in Code Snippets, General Programming | Posted on 01-02-2011

0

Today one of my co-workers send me the following link.
As I couldn’t believe my eyes, I have tested it myself.
WTF?

package wtfjava;

/**
 * This program really HANGS!!!!
 * @author kris
 */

public class Main {

    /**
     * @param args the command line arguments
     */

    public static void main(String[] args) {
        System.out.println("Test:");
        double d = Double.parseDouble("2.2250738585072012e-308");
        System.out.println("Value: " + d);
    }
}

Design Patterns – Part Three: Singleton

Posted by admin | Posted in Code Snippets, General Programming | Posted on 01-02-2011

1

Today I will describe the Singleton pattern, one of the simplest, yet generating active discussions all over the net. Some people consider it to be an antipattern. We have many different flavours of this pattern, singleton can be thread safe, lazy loaded, eagerly loaded, implemented as a static class or enum.
Simple thread safe implementation:

/**
 * This solution uses class loading mechanizm and its
 * thread safe
 * @author kris
 * @version 01-02-2011
 */

public class FirstSingleton {
    static class FirstSingletonHolder {
        static final FirstSingleton INSTANCE = new FirstSingleton();
    }
    public static FirstSingleton getInstance() {
        return FirstSingletonHolder.INSTANCE;
    }
}

Simple lazy loading implementation:

/**
 * Lazy loaded version of singleton pattern
 * @author kris
 * @version 01-02-2011
 */

public class SecondSingleton {
        private static SecondSingleton instance = null;

        private SecondSingleton() {}

        public static SecondSingleton getInstance() {
              if(null == instance) {
                  synchronized(SecondSingleton.class) {
                      if(null == instance) {
                          instance = new SecondSingleton();
                      }
                  }
               }
               return instance;
        }

        protected Object clone() throws CloneNotSupportedException {
            throw new CloneNotSupportedException();
        }
}

Enum implementation of Singleton pattern (according to J.Bloch the best implementation availalble)

“This approach is functionally equivalent to the public field approach, except that it is more concise, provides the serialization machinery for free, and provides an ironclad guarantee against multiple instantiation, even in the face of sophisticated serialization or reflection attacks. While this approach has yet to be widely adopted, a single-element enum type is the best way to implement a singleton.”

/**
 * Enum implementation of singleton design pattern
 *
 * @author Krzysztof Grajek
 * @version 01-02-2011
 */

public enum EnumSingleton {
    INSTANCE;

    private String name;

    public String getName(){
        return name;
    }
}

If you feel that singleton is the right solution to your problem, use the one which is shortest/simplest and available in your environment (enum version J2EE 5+)

Design Patterns Series – Part Two: Template Method

Posted by admin | Posted in Code Snippets, General Programming | Posted on 31-01-2011

0

A typical template method pattern consists of the abstract base class which defines one or more template methods (usually set as final) and some abstract methods which the subclass has to implement. Template method defines common algorithm where some of the steps are implemented by subclasses.

A Template method pattern provides a skeleton for performing any sort of algorithm or an operation, and it allows the sub-classes to re-define part of the logic

This is one of the easiest design patterns and has a very simple UML model:

AmazonKindle.java

package com.softwarepassion.templatemethodpattern;


/**
 * Defines a template for assembling Amazon Kindle Devices
 *
 * @author kris
 * @version 31-01-2011
 */

public abstract class AmazonKindle {

    public AmazonKindle(){
       
    }
    /**
     * Example of Template Method design pattern
     */

    public final void assembleAmazonKindle(){
        createKindleCase();
        setDisplay();
        addModem();
        printSpecs();
    }
   
    public abstract void  createKindleCase();
    public abstract void setDisplay();
    public abstract void addModem();

    private void printSpecs() {
        System.out.println("Printing Amazon Kindle specs..");
    }
}

AmazonKindle6WiFi.java

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */


package com.softwarepassion.templatemethodpattern;

/**
 * Concrete implementation of {@code AmazonKindle}
 * with 6" screen and WiFi modem
 * assembled in a standard way using a template
 * @author kris
 * @version 31-01-2011
 */

public class AmazonKindle6WiFi extends AmazonKindle{

    @Override
    public void createKindleCase() {
        System.out.println("creates a kindle case for 6\" kindles");
    }

    @Override
    public void setDisplay() {
        System.out.println("adds a 6\" display");
    }

    @Override
    public void addModem() {
        System.out.println("adds a WiFi modem");
    }

}

AmazonKindle6_3G.java

package com.softwarepassion.templatemethodpattern;

/**
 * Concrete implementation of {@code AmazonKindle}
 * with 6" screen and 3G modem
 * assembled in a standard way using a template
 *
 * @author kris
 * @version 31-01-2011
 */

public class AmazonKindle6_3G extends AmazonKindle{

    @Override
    public void createKindleCase() {
        System.out.println("creates a kindle case for 6\" kindles");
    }

    @Override
    public void setDisplay() {
        System.out.println("adds a 6\" display");
    }

    @Override
    public void addModem() {
        System.out.println("adds a 3G modem");
    }
}

Main.java for simple testing..

public class Main {

    /**
     * @param args the command line arguments
     */

    public static void main(String[] args) {
        System.out.println("Assembling amazon kindles");
        //assembling wifi kindle
        AmazonKindle kindle = new AmazonKindle6WiFi();
        Main main = new Main();
        main.assembleAmazonKindle(kindle);
        //assembling 3g kindle
        kindle = new AmazonKindle6_3G();
        main.assembleAmazonKindle(kindle);
    }
    public void assembleAmazonKindle(AmazonKindle kindle){
        kindle.assembleAmazonKindle();
    }

}

Design Patterns Series – Part One: Strategy Pattern

Posted by admin | Posted in Code Snippets, General Programming, Learning Materials | Posted on 28-01-2011

1

The Strategy Pattern is a first pattern described in a series of post I’m planning to make regarding this topic. The Strategy pattern allows us to select a specific algorithm at runtime and its one of the simples design patterns to grasp.
The scenario described on the diagram below shows a simple usage of the strategy pattern.

Let’s say we have a HttpServlet which creates a report using data retrieved from the request parameters, or some other sources like database. and depending on which kind of report we want to create (PDF, DOC or HTML) chooses appropriate algorithm to do just that.
So w end up with common interface for creating reports called ‘ReportGenerator’ with a single method ‘generateReport(ReportData rd)’:

/*
 * Created by softwarepassion.com
 * Any information regarding license for this code snippets and
 * other copyright info can be found @softwarepassion.com
 * The author doesn't take any reposnsibility for the presented
 * code and design patterns solutions.
 * Please be advised that this code can contain errors!
 *
 */


package strategydesignpattern;

/**
 * Common interface for generating reports using different formats
 *
 * @author Krzysztof Grajek
 * @version 28-01-2011
 */

public interface ReportGenerator {

    /**
     * Generates report using provided report data
     * @param rd ReportData object carrying all info needed to produce report
     */

    public void generateReport(ReportData rd);
}

We have three different implementations of this interface, allowing us to generate report in a form of PDF, DOC or HTML format.
PDF Report Generator:

/*
 * Created by softwarepassion.com
 * Any information regarding license for this code snippets and
 * other copyright info can be found @softwarepassion.com
 * The author doesn't take any reposnsibility for the presented
 * code and design patterns solutions.
 * Please be advised that this code can contain errors!
 *
 */


package strategydesignpattern;

/**
 * Responsible for handling PDF reports
 *
 * @author Krzysztof Grajek
 * @version 28-01-2011
 */

public class PDFReportGenerator implements ReportGenerator {

    public void generateReport(ReportData rd) {
        System.out.println("Generating PDF report..." + rd.getTitle());
    }

}

Microsoft Word Generator:

/*
 * Created by softwarepassion.com
 * Any information regarding license for this code snippets and
 * other copyright info can be found @softwarepassion.com
 * The author doesn't take any reposnsibility for the presented
 * code and design patterns solutions.
 * Please be advised that this code can contain errors!
 *
 */


package strategydesignpattern;

/**
 * Responsible for handling reports in MS Word format
 *
 * @author Krzysztof Grajek
 * @version 28-01-2011
 */

public class MsDOCReportGenerator implements ReportGenerator{

    public void generateReport(ReportData rd) {
        System.out.println("Generating MS Word report.. " + rd.getTitle());
    }

}

HTML Report Generator:

/*
 * Created by softwarepassion.com
 * Any information regarding license for this code snippets and
 * other copyright info can be found @softwarepassion.com
 * The author doesn't take any reposnsibility for the presented
 * code and design patterns solutions.
 * Please be advised that this code can contain errors!
 *
 */


package strategydesignpattern;

/**
 * Responsible for generating reports in HTML format
 *
 * @author Krzysztof Grajek
 * @version 28-01-2011
 */

public class HTMLReportGenerator implements ReportGenerator{

    public void generateReport(ReportData rd) {
        System.out.println("Generating HTML report..." + rd.getTitle());
    }

}

All mentioned above generators use a single object (simple POJO class) containing the data needed to generate report ReportData

/*
 * Created by softwarepassion.com
 * Any information regarding license for this code snippets and
 * other copyright info can be found @softwarepassion.com
 * The author doesn't take any reposnsibility for the presented
 * code and design patterns solutions.
 * Please be advised that this code can contain errors!
 */


package strategydesignpattern;

/**
 * Used to transport data needed to produce report
 * in any form using {@link ReportGenerator}
 *
 * @author Krzysztof Grajek
 * @version 28-01-2011
 */

public class ReportData {

    private String title;
    private String description;
    //...other report related stuff needed to produce report

    //..getters and setters for the class fields
    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
   
}

All of different kinds of generators can be used in our simple report servlet:

/*
 * Created by softwarepassion.com
 * Any information regarding license for this code snippets and
 * other copyright info can be found @softwarepassion.com
 * The author doesn't take any reposnsibility for the presented
 * code and design patterns solutions.
 * Please be advised that this code can contain errors!
 *
 */


package strategydesignpattern;

/**
 * Example class using {@code ReportGenerator} interface
 * This class mimmicks the behaviour of a http servlet, assuming that all needed
 * parameters for generating report are coming from the database or in the form
 * of servlet request parameters contained in a single {@code ReportData } object,
 * we choose one of the available report generators
 * to generate our report.
 *
 * @author Krzysztof Grajek
 * @version 28-01-2011
 */

public class MockReportServlet {

    private ReportGenerator reportGenerator;

    public void onGet(String request, String response){
        //1. get the data from the database, request parameters or any other source
        //in the form of ReportData object
        ReportData reportData = new ReportData();
        reportData.setTitle("Design Patterns Report for: Strategy Pattern");
        //2. Using the request parameter decide on which one of three report generators
        //to use when generating the report
       
        //3. Assuming that PDF generator was selected by the user generate PDF report
        if("PDF".equals(request)){
            reportGenerator = new PDFReportGenerator();
            reportGenerator.generateReport(reportData);
        }
    }
}

The source code for this example (in the form of Netbeans project) can be found here

Simple Guide to basic Javadoc

Posted by admin | Posted in General Programming | Posted on 27-01-2011

1

Javadoc tool is in my opinion one of the most underestimated tools available for a Java developer. Recently I have started digging into some opensource projects when looking for a nice examples of design patterns and I was surprised at high quality of their code in terms of commenting. This is something I, and many people I know, forget to do while producing source code every day.
Following the principle to leave the source in a better condition every time we open it in the IDE, I will leave here a simple example of a nice and clean class comment:

(example from JHotDraw)

/**
* Tool to select and manipulate figures.
*

* A selection tool is in one of three states: 1) area
* selection, 2) figure dragging, 3) handle manipulation. The different
* states are handled by different tracker objects: the
* <code>DefaultSelectAreaTracker</code>, the <code>DefaultDragTracker</code> and the
* <code>DefaultHandleTracker</code>.
*

* A Figure can be selected by clicking at it. Holding the alt key or the
* ctrl key down, selects the Figure behind it.
*

<hr />
* <strong>Design Patterns</strong>
*
*

<em>Strategy</em>

* The different behavior states of the selection tool are implemented by
* trackers.

* Context: {@link SelectionTool}; State: {@link DragTracker},
* {@link HandleTracker}, {@link SelectAreaTracker}.
*
*

<em>Chain of responsibility</em>

* Mouse and keyboard events of the user occur on the drawing view, and are
* preprocessed by the {@code DragTracker} of a {@code SelectionTool}. In
* turn {@code DragTracker} invokes "track" methods on a {@code Handle} which in
* turn changes an aspect of a figure.

* Client: {@link SelectionTool}; Handler: {@link DragTracker}, {@link Handle}.
*

<hr />
*
* @author Werner Randelshofer
* @version $Id: SelectionTool.java 718 2010-11-21 17:49:53Z rawcoder $
*/

public class SelectionTool extends AbstractTool{
.................... class source code ..........
}

Some comments on the comment itself:

1. Use

style for keywords and names.
Keywords and names are offset by

<code>...</code>

when mentioned in a description. This includes:

* Java keywords
* package names
* class names
* method names
* interface names
* field names
* argument names
* code examples

2. add links for API names (listed immediately above) using the

{@link}

tag. It is not necessary to add links for all API names in a doc comment. Because links call attention to themselves (by their color and underline in HTML, and by their length in source code doc comments).

3. User @Code instead of if you have to include some special chars in it eg.

 {@code Outer<S>.Inner<T>}

see the Joseph D. Darcy's Oracle Weblog for more info.

4. Use the @author tag and don't be ashamed of your code :)

See more example of good commenting in JHotDraw project