Tuesday, 27 December 2011

Critical Success Factors Of Object Oriented Frameworks

There are a lot of Frameworks out there. Making a decision on which one to use is sometimes extremely hard to do.

I found some rules at http://c2.com/cgi/wiki?CriticalSuccessFactorsOfObjectOrientedFrameworks, which I will summarize here for my convenience. (You didn't think I wrote this blog for you, do you?)

  • Iterative development
    changing requirements/uses/etc
  • Understandability
    nature of the framework, documentation
  • Quality
    faith of your users
  • Appropriateness
    time, skillevel of team, size, domain, use

Wednesday, 14 December 2011

Netbeans Tips & Tricks

Contents

Netbeans 7.0.1. doesn't validate jdk 7.0 syntax in editor

Netbeans 7.0.1. doesn't start

How to automatically use a License in your new java files

Changing indentation style


Netbeans 7.0.1. doesn't validate jdk 7.0 syntax in editor

For example, editor complains about: "try-with-resources is not supported in -source 1.6 (use -source 7 or higher to enable try-with-resources)" in a try-with-resources block.

Right click project. Properties. Sources. Source-binary->jdk7. No problems after that.

Of course, there's still the problem that the new syntax in the JSP pages doesn't work.

Jk7 doesn't work with jsp pages yet, see http://java.net/jira/browse/GLASSFISH-17429 .


Netbeans 7.0.1. doesn't start

I just downloaded Netbeans 7.0.1 from http://www.oracle.com/technetwork/java/javase/downloads.

It didn't work.

No output on the console, either.

However, I was able to run Netbeans correctly from the root account.

It turns out that I had the settings of a previous version of Netbeans in my homedir. To wit:

  • .netbeans/
  • .netbeans-derby/
  • .netbeans-registration/

After removing said settings, netbeans started properly and created the setting directory .netbeans.

Hope it helps someone.


How to automatically use a License in your new java files

Add project.license=gpl30 (for example) to your project.properties file in nbproject directory of your project.


But there are easier ways to do it in Netbeans 7.4. Choose Project properties, select "License Headers" and just set the Global license to for example General Public License 3.0

Changing indentation style

To change editor settings.

Click the Tools > Options menu item.

In the icon display, click Editor.

In the right panel, select the category "Tabs and Indents" tab.

If it isn't already done, set the following:

Statement continuation Indent: 8

Number of Spaces per Indent: 4

Check Expand Tabs to Spaces.

In the right panel, select the category "Braces" tab.

If you like the Allman indentation style (like me), check the "New Line" for a Class declaration, Method declaration and Other.

References

NetBeans IDE
http://leepoint.net/notes-java/tools/netbeans/netbeans.html
Project-Level License Settings in NetBeans IDE 6.0
http://blogs.oracle.com/geertjan/entry/project_level_license_settings_in

Monday, 12 December 2011

Implicit Default Constructor - good or bad?

Everyone who knows Java, knows that if you do not define a constructor in a class, the default constructor is implicitly created by the compiler.[1]

Is this a good thing or a bad thing?

Good thing:

  • we need a constructor to instantiate an object, and if we forget to make one we can simply use the default constructor.

Bad thing:
  • creating a new constructor with arguments, automatically will make the compiler NOT create the implicit default constructor, perhaps causing breakage in your program/application.

So, should we do the following?

package mrbear;

public class Main
{

    /**
     * Explicit Default Constructor. Required.
     * Defined here to prevent problems when
     * new constructor(s) with different arguments is/are added.
     */

    public Main()
    {
    }

}

I know for a fact, for example, that Hibernate requires entities to have some sort of default constructor, so Hibernate can create objects using reflection. [2]

You'd see something in the log like:

10:54:15,575 INFO [PojoInstantiator] no default (no-argument) constructor for class: mrbear.Main (class must be instantiated by Interceptor)

References

[1] Providing Constructors for Your Classes
http://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html
[2] Hibernate : Chapter 4. Persistent Classes
http://docs.jboss.org/hibernate/core/3.3/reference/en/html/persistent-classes.html

Sunday, 9 October 2011

Different Ways to use JPQL

Introduction

There are several ways in which to execute JPQL (Java Persistence Query Language). I'll introduce the "old way" first, with JDBC and direct connections to the database, before branching off into the ways used by ORMs (Object Relational Mapping).

Each way has its advantages and disadvantages.

The old way:
  • direct database access
  • database connection pool
Using an ORM
  • hql in java code
  • named queries in annotations
  • named queries in xml
  • Criterion API
  • retrieving the object by its primary key

The Old Way

Direct Database Access

This is an example of direct database connection with jdbc. Setting it up, sending the query, reading the result, close the resultset and shutting down the connection.


/**
 * Connects to the database using an url. The url looks something like
 * "jdbc:mysql://localhost.localdomain/mud?user=root&password=". Uses the
 * classname in Constants.dbjdbcclass to get the right class for interfacing
 * with the database server. If the database used is changed (or to be more
 * specific the jdbc driver is changed) change the constant.
 * 
 * @throws InstantiationException
 *             happens when it is impossible to instantiate the proper
 *             database class, from the class name as provided by
 *             Constants.dbjdbcclass.
 * @throws ClassNotFoundException
 *             happens when it is impossible to find the proper database
 *             class, from the class name as provided by
 *             Constants.dbjdbcclass.
 * @throws IllegalAccessException
 *             happens when it is not possible to create the database class
 *             because access restrictions apply.
 * @throws SQLException
 *             happens when a connection to the database Server could not be
 *             established.
 */

public Macro runQuery() throws SQLException, InstantiationException,
    ClassNotFoundException, IllegalAccessException
{
  Macro result = null;
  try
  {
    Class.forName(Constants.dbjdbcclass).newInstance();

    // jdbc:mysql://[host][,failoverhost...][:port]/[database]
    // [?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]...
    String theUrl = Constants.dburl + "://" + Constants.dbhost
      + Constants.dbdomain + "/" + Constants.dbname + "?user="
      + Constants.dbuser + "&password=" + Constants.dbpasswd;
    theConnection = DriverManager.getConnection(theUrl);

    PreparedStatement statGetMacro = null;
    statGetMacro = theConnection.prepareStatement(sqlGetMacro);
    statGetMacro.setString(2, macroname);
    res = statGetMacro.executeQuery();
    if (res != null && res.next())
    {
      result = new Macro(res.getString("macroname"), res.getString("contents"));
      res.close();
    }
    statGetMacro.close();
  } catch (Exception e)
  {
    throw new MudDatabaseException(Constants.DATABASECONNECTIONERROR, e2);
  }
  finally
  {
    if (theConnection != null) {theConnection.close();}
  }
  return result;
}
Advantages:
  • complete control
  • very little libraries required
Disadvantages:
  • sql syntax spread throughout the java code
  • lots of error-prone boiler plate code required
  • expensive in setting up new database connections for every query
  • sytax of query not checked, until method called
  • changing the query requires source code change, recompilation, repackaging, etc

Database Connection Pool

This is example of database connection with jndi resource pool, where the only thing required is the jndi name. In this case it is irrelevant which connection we receive from the connection pool. The actual theConnection.close() does nothing, but returns the connection back to the pool.


public void runQuery() throws Exception
{
  Connection con=null;
  ResultSet rst=null;
  PreparedStatement stmt=null;

  try
  {
    Context ctx = new InitialContext();
    DataSource ds = (DataSource) ctx.lookup("jdbc/mmud");
    con = ds.getConnection();

    stmt=con.prepareStatement("select * from links where type = 1 order by creation");
    rst=stmt.executeQuery();
    while(rst.next())
    {
        out.println("<li><A HREF=\"" + rst.getString("url") + "\">" +
          rst.getString("linkname") + "</A> (<i>" +
          rst.getString("name") + "</i>)<P>");
    }
    rst.close();
    stmt.close();
  }        
  finally
  {
    if (rst != null) {try {rst.close();} catch (Exception e){}}
    if (stmt != null) {try {stmt.close();} catch (Exception e)}}
    if (con != null) {try {con.close();} catch (Exception e){}}
  }
}

Advantages:
  • database connection resource pool
  • no need to open and close connection, connections are reused
Disadvantages:
  • sql syntax spread throughout the java code
  • still a lot of error-prone boiler plate code required
  • sytax of query not checked, until method called
  • if connections/resources not properly released, the pool will run out of connections/resources
  • changing the query requires source code change, recompilation, repackaging, etc

Using an ORM

hql in java code

@Override
public void deleteAddress() 
{
  StringBuilder queryBuilder = new StringBuilder();
  queryBuilder.append("DELETE Address address ");
  queryBuilder.append("WHERE  address.country = 'Italy' ");
  queryBuilder.append("AND NOT EXISTS (SELECT '' ");
  queryBuilder.append("            FROM Customer cust ");
  queryBuilder.append("            WHERE cust.address = address ");
  queryBuilder.append("           ) ");

  Query query = em.createQuery(queryBuilder.toString());
  query.executeUpdate();
}

Unfortunately, the code above is what I encounter frequently in the source of my employers current software product.

Advantages:
  • none
Disadvantages:
  • a StringBuffer is created every time the method is called, at the very least this should be a constant
  • jpql is created and parsed and compiled every time the method is called
  • sql/hql/jpql syntax spread throughout the java code
  • sytax of query not checked, until method called
  • changing the query requires source code change, recompilation, repackaging, etc


Named queries in annotations

Queries can be defined in the annotations on top of Entity classes. The annotation would look a little like the one below.

@NamedQueries({
    @NamedQuery(name = "Character.findAll", query = "SELECT c FROM Character c"),
    @NamedQuery(name = "Character.findByName", query = "SELECT c FROM Character c WHERE c.name = :name")})

One of the problems often heard is that the annotation has to be on an Entity class, when you perhaps would prefer to have it someplace else. In that case, it might be an idea to define the constants as strings in a different part, like a Service or a DAO or what have you, and refer to them in the NamedQuery annotations. Like in the two-part example below.

As the name of a named query is global within the persistent provider, it is essential to create unique names within the application. That is why in most cases, the name of a named query is prefixed with the class name.

/**
 * Game bean.
 * @author Mr. Bear
 */

@Stateless
@Remote(GameBeanRemote.class)
public class GameBean implements GameBeanRemote
{
    public static final String character = "Character";

    /**
     * label for the find all characters query.
     */

    public static final String FINDALLCHARS_QUERYNAME = character + ".findAll";

    /**
     * query for the find of all characters query.
     */

    public static final String FINDALLCHARS_QUERY = "SELECT c FROM Character c";

    /**
     * label for the find character based on name query.
     */

    public static final String FINDCHAR_QUERYNAME = character + ".findByName";

    /**
     * query for the find of character based on name query.
     */

    public static final String FINDCHAR_QUERY = "SELECT c FROM Character c WHERE c.name = :name";

    @PersistenceContext(unitName = "datasource")
    private EntityManager em;
/**
 * The Character entity.
 * @author Mr. Bear
 */

@Entity
@Table(name = "mm_usertable")
@NamedQueries({
   @NamedQuery(name = GameBean.FINDALLCHARS_QUERYNAME, query = GameBean.FINDALLCHARS_QUERY),
   @NamedQuery(name = GameBean.FINDCHAR_QUERYNAME, query = GameBean.FINDCHAR_QUERY)})
public class Character implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 20)
    @Column(name = "name")
    private String name;

Using the named queries in code is as simple as getting the entity manager and telling him the name of the NamedQuery you wish to use, add the parameter values, and request the result. You can refer to the NamedQueries by name, hence the name, get it?

@Override
public CommandOutput retrieveCharacter(String name)
{
    itsLog.entering(this.getClass().getName(), "retrieveCharacter");
    Query q = em.createNamedQuery("Character.findByName", Character.class);
    q.setParameter("name", name);
    Character c = (Character) q.getSingleResult();
    if (c == null)
    {
        itsLog.exiting(this.getClass().getName(), "retrieveCharacter");
        return new CommandOutput("""""");
    }
    CommandOutput co = new CommandOutput(c.getName(), c.getArm(), c.getBeard());
    itsLog.exiting(this.getClass().getName(), "retrieveCharacter ", co);
    return co;
}

The great part of NamedQueries is that they are checked and pre-compiled by Hibernate when the server starts, so you get instant messages if you screwed up the syntax.

Advantages:
  • the Persistence provider might be able to precompile them, and this can help catch bugs before deployment
  • sql syntax no longer spread throughout the java code
  • sql queries externalised to the java code
  • there's a central place for queries, making them easy to find and easy to re-use.
Disadvantages:
  • named queries in annotations can only be added to the Entity classes or the SuperMapClass. This is especially awkward when you have a query spanning multiple entities.
  • named queries are referenced using a key, which is global to the application.
  • named queries are a little difficult to debug, as a change requires an application server reboot.
  • changing the query in the annotation requires source code change, recompilation, repackaging, etc

In the examples below, JBoss is used in combination with Hibernate. The first example is the jboss log when things go wrong, and the second example is when things go right.

09:19:23,635 ERROR [SessionFactoryImpl] Error in named query: FullAddress.findAddressesOfCustomers
org.hibernate.QueryException: could not resolve property: entitynr of: mrbear.entity.Address [DELETE Address address WHERE address.country = 'Italy' AND address.entitynr > 1000 AND NOT EXISTS (SELECT '' FROM Customer cust WHERE cust.address = address) ]
at org.hibernate.persister.entity.AbstractPropertyMapping.propertyException(AbstractPropertyMapping.java:67)
09:23:10,946 INFO [AnnotationBinder] Binding entity from annotated class: mrbear.entity.Address
09:23:10,948 INFO [QueryBinder] Binding Named query: FullAddress.findAddressesOfCustomers => DELETE Address address WHERE address.country = 'Italy' AND address.entityNr > 1000 AND NOT EXISTS (SELECT '' FROM Customer cust WHERE cust.address = address)

Let me point you especially to the fact that HQL (or JPQL for that matter), contrary to SQL, is case-sensitive (for the most part). It would have to be, as it has a direct link to java classes and these are also case-sensitive.

In the example above, the getter and setter for entity number was specified as getEntityNr and setEntityNr, hence the problem with the casing in the first example.

According to Gavin King [1]:
We leave it up to you if you want to utilize the named query feature. However, we consider query strings in the application code (except if they're in annotations) to be the second choice; you should always externalize query strings if possible.

Named queries in xml

If you do not like to have your JPQL in your code at all, there is always the possibility of putting the queries into the xml files that are a part of the configuration of the jar file.

There is no reason why you cannot have both, both named queries in your annotations and queries in your xml persistence configuration files.

One of the great things is that the named queries in the persistence xml files take precedence over the named queries in the annotations. This means, that, when deployed in a specific production environment, it is possible to change the named queries, without having to touch/recompile/build/package the java source code. So, you can do convention over configuration.

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="mmud" transaction-type="JTA">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>mmud</jta-data-source>
    <!-- Named JPQL queries per entity, but any other organization is possible  -->
    <mapping-file>META-INF/jpql/Character.xml</mapping-file>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties/>
  </persistence-unit>
</persistence>
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings version="1.0" xmlns="http://java.sun.com/xml/ns/persistence/orm"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd "
>

    <named-query name="Character.findByName">
        <query>
            SELECT
                c
            FROM
                Character c
            WHERE
                c.password = :name
            OR
                c.name = 'Midevia'
        </query>
    </named-query>
</entity-mappings>

So in the code example that uses annotations, when using these two persistence xml files displayed above, suddenly "Midevia" is retrieved from the database, instead of the name you requested.

Advantages:
  • the Persistence provider might be able to precompile them, and this can help catch bugs before deployment
  • sql syntax no longer anywhere in the java code
  • there's a central place for queries, making them easy to find and easy to re-use.
  • named queries can be spread through many different xml files, making them more easy to categorise.
Disadvantages:
  • named queries are referenced using a key, which is global to the application.
  • named queries in xml, can be changed, if you don't mind hacking your way through xml.
  • named queries are a little difficult to debug, as a change requires an application server reboot.

Criterion API

@Override
public CommandOutput retrieveCharacter(String name)
{
    itsLog.entering(this.getClass().getName(), "retrieveCharacter");

    // setup criteria builders/queries
    CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
    CriteriaQuery criteriaQuery = criteriaBuilder.createQuery();

    // add from
    Root<Character> from = criteriaQuery.from(Character.class);
    CriteriaQuery<Character> select = criteriaQuery.select(from);

    // add predicate
    Predicate predicate = criteriaBuilder.equal(from.get("name"), name);
    criteriaQuery.where(predicate);

    // create the select query
    TypedQuery<Character> typedQuery = em.createQuery(select);

    // get the results
    List<Character> resultList = typedQuery.getResultList();

    if (resultList == null || resultList.size() != 1)
    {
       itsLog.exiting(this.getClass().getName(), "retrieveCharacter");
       return new CommandOutput("""""");
    }
    CommandOutput co = new CommandOutput(
            resultList.get(0).getName(),
            resultList.get(0).getArm(),
            resultList.get(0).getBeard());
    itsLog.exiting(this.getClass().getName(), "retrieveCharacter ", co);
    return co;
}
Advantages:
  • the Persistence provider might be able to precompile them, and this can help catch bugs before deployment
  • sql syntax no longer anywhere in the java code
  • the query is dynamic, making it easy to change depending on input from the user
  • it is java, so every tool and compiler can aid in the development, like syntax checking and type checking and the like
Disadvantages:
  • fairly unreadable

Retrieving the object by its primary key

Ideally, we do not wish to use SQL or HQL or the Criteria API at all. If possible, we just want to tell the Entity Manager to get the objects we need. In most cases, this is not easy. But for some concepts, like getting an object based on its primary key (so we are always sure there's just one (or zero) available) there's a much more straightforward way.

@Override
public CommandOutput retrieveCharacter(String name)
{
    itsLog.entering(this.getClass().getName(), "retrieveCharacter");
    Character c = em.find(Character.class, name);
    if (c == null)
    {
        itsLog.exiting(this.getClass().getName(), "retrieveCharacter");
        return new CommandOutput("""""");
    }
    CommandOutput co = new CommandOutput(c.getName(), c.getArm(), c.getBeard());
    itsLog.exiting(this.getClass().getName(), "retrieveCharacter ", co);
    return co;
}
Advantages:
  • no SQL/HQL/JPSQL of any kind required
  • the JPA implementation can cache the object and retrieve is quickly.
Disadvantages:
  • only for specific uses, like retrieving objects by primary key.

Conclusion

I hope to have demonstrated the different uses that exist in retrieving data from a database using any kind of ORM, compatible with the JPA. As you are no doubt aware from this piece, I strongly consider the last four examples to be good practices of creating JPQL queries in your application.

As always, each has its strong and weak points, and therefore are applicable to different situations. Evaluate the situation and pick the one that is best suited for the job.

References


[1] Java Persistence with Hibernate
Christian Bauer, Gavin King
[2] chapter 2.3 - Hibernate Community Documentation
http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/
[3] Organize Your Named JPQL Queries
http://eubauer.de/kingsware/2011/03/25/organize-your-named-jpql-queries/
[4] Hibernate: Criteria vs. HQL
http://stackoverflow.com/questions/197474/hibernate-criteria-vs-hql
[5] Are Hibernate named HQL queries (in annotations) optimised?
http://stackoverflow.com/questions/2641997/are-hibernate-named-hql-queries-in-annotations-optimised
[6] GlassFish Project - Java Persistence Example
http://glassfish.java.net/javaee5/persistence/persistence-example.html
[7] Use string constants in annotations
http://javahowto.blogspot.com/2009/04/use-string-constants-in-annotations.html
[8] Java Persistence 2.0 Public Draft: Criteria API
http://blogs.oracle.com/ldemichiel/entry/java_persistence_2_0_public1
[9] Dynamic, typesafe queries in JPA 2.0
http://www.ibm.com/developerworks/java/library/j-typesafejpa/
[10] Where to put named queries in JPA?
http://jdevelopment.nl/put-named-queries-jpa/
[11] Java Glossary
http://randomthoughtsonjavaprogramming.blogspot.com/p/glossary.html

Wednesday, 5 October 2011

Constructor in Anonymous Inner Class

Recently, I've been playing with JMockit, and I've come across certain language constructs in java that confused me.

It appears they were related to creating a different body for a constructor in the inner anonymous class. Which is hard to do, as the name of the Anonymous Inner Class is unknown.

package mrbean.anonymous;

public class Anonymous 
{

  private int i = 5;

  public int getI() 
  {
    System.out.println(this + " getI");
    return i;
  }

  public void setI(int i) 
  {
    System.out.println(this + " setI");
    this.i = i;
  }

  public Anonymous() 
  {
    System.out.println(this + " Constructor");
  }

  public void doStuff() 
  {
    System.out.println(this + " doStuff");
    System.out.println("i=" + new Anonymous() {
      {
        System.out.println(this + " Anonymous Constructor");
        setI(10);
      }
    }.getI());
  }

  /**
   * Main method to start the program.
   * @param args arguments
   */

  public static void main(String[] args) 
  {
    System.out.println("main: Start program.");
    Anonymous first = new Anonymous();
    System.out.println("main: i=" + first.getI());
    first.doStuff();
    System.out.println("main: End program.");
  }

}

This provided me with the following output:

main: Start program.
mrbear.anonymous.Anonymous@7d8a992f Constructor
mrbear.anonymous.Anonymous@7d8a992f getI
main: i=5
mrbear.anonymous.Anonymous@7d8a992f doStuff
mrbear.anonymous.Anonymous$1@23fc4bec Constructor
mrbear.anonymous.Anonymous$1@23fc4bec Anonymous Constructor
mrbear.anonymous.Anonymous$1@23fc4bec setI
mrbear.anonymous.Anonymous$1@23fc4bec getI
i=10
main: End program.

Especially in the creation of Expectations and Verifications in test methods in JMockit, it's quite common.

Saturday, 1 October 2011

Creating Hello World in Netbeans IDE 7.0.1 and Glassfish 3.1

A simple attempt of mine to create a HelloWorld Enterprise JavaBean (EJB) in Netbeans 7.0.1. and Glassfish 3.1.

Primary use is for me to remember how to do this, and what needs to be configured to make it work.

Creating the JEE Application

First, start up your brand new Netbeans 7.0.1. and select a new project.

Select Java Enterprise Applications.





It will start creating the new project. You will end up with three new projects.


First of the projects, HelloWorldEE is the EAR file, which is a jar-file that is to be deployed to the glassfish server. It consists of two jar-files, that are created by the other two projects.

Second is HelloWorldEE-ejb, the project that is to contain our new Enterprise Java Beans (EJB).

Third is HelloWorldEE-war, the project that is to contain all the web stuff, like jsp pages, servlets, and what have you.

Let's create our first Enterprise Java Bean.



Here I've selected a Local interface for now. You'll notice two java files are generated, one containing the local interface and one containing the implementation.

We will add a business method.




Change the helloWorld method to return the string "Hello, world.". Now, in order to test it, we are going to create a java client that connects to the bean using Corba. However, for this to work, the interfaces need to be Remote, and not Local. Change the source code accordingly.

Your source code should look something like this:

package mrbear.beans;

import javax.ejb.Remote;

/**
 * The remote interface to my bean.
 * @author Mr. Bear
 */

@Remote
public interface MyFirstBeanRemote {

    /**
     * Returns the string "Hello, world."
     * @return String with text.
     */

    public String helloWorld();
    
}
package mrbear.beans;

import javax.ejb.Stateless;

/**
 * My first enterprise java bean.
 * @author Mr. Bear
 */

@Stateless
public class MyFirstBean implements MyFirstBeanRemote {

    @Override
    public String helloWorld() {
        return "Hello, world.";
    }

}

In the war project, a jsp page is automatically generated upon creation of the project, and it will help to check if the ear file was successfully deployed.

Try and "run" the project HelloWorldEE. A GlassFish 3.1 server will be started by Netbeans, the ear file deployed, and a webpage will be visible at url http://localhost:8080/HelloWorldEE-war/. It should show "Hello world!". Now, make no mistake! This is not our bean! This is the jsp page that is generated automatically in the war project. It shows that at least the ear file was successfully deployed.

The jsp file can be found at HelloWorldEE/HelloWorldEE-war/web/index.jsp

In your output window (HelloWorldEE(run)), you should see something like this:

Starting GlassFish Server 3.x
GlassFish Server 3.x is running.
Initial deploying HelloWorldEE to /home/mrbear/NetBeansProjects/HelloWorldEE/dist/gfdeploy/HelloWorldEE
Completed initial distribution of HelloWorldEE
Initializing...
Browsing: http://localhost:8080/HelloWorldEE-war

In the GlassFish log, you should see something like this:

INFO: Portable JNDI names for EJB MyFirstBean : [java:global/HelloWorldEE/HelloWorldEE-ejb/MyFirstBean, java:global/HelloWorldEE/HelloWorldEE-ejb/MyFirstBean!mrbear.beans.MyFirstBeanRemote]
INFO: WEB0671: Loading application [HelloWorldEE#HelloWorldEE-war.war] at [HelloWorldEE-war]
INFO: HelloWorldEE was successfully deployed in 5,409 milliseconds.

Pay special attention to the JNDI names used for the EJB MyFirstBean. We'll need those to create our HelloWorld java client.

Your bean should now be alive and kicking! You can check this by browsing to the administration console of your Glassfish server at http://localhost:4848/.


Creating the Java Client

Time to create a new project. Create a new project, and select Enterprise Application Client.





You do need to add a dependency in the HelloWorldClient to the HelloWorldEE-ejb (which resides in the HelloWorldEE) by selecting "add Project" in the Compile tab of "Libraries" of the Helloworld java client project.


Your java client source code in the main method should look something like this:

package helloworldclient;

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import mrbear.beans.MyFirstBeanRemote;

/**
 * The client for connecting to the MyFirstBean bean.
 * @author Mr. Bear
 */

public class Main {

    /**
     * Main method, called when executing this program.
     * @param args the command line arguments
     */

    public static void main(String[] args) {
        System.out.println("Starting...");

        System.out.println("Establishing connection to the bean...");
        MyFirstBeanRemote example;
        try {
            InitialContext initialContext = new InitialContext();

            // INFO: Portable JNDI names for EJB MyFirstBean : 
            // java:global/HelloWorldEE/HelloWorldEE-ejb/MyFirstBean
            example = (MyFirstBeanRemote) initialContext.lookup("java:global/HelloWorldEE/HelloWorldEE-ejb/MyFirstBean");
            System.out.println("Calling method on the bean...");
            System.out.println("     Result: " + example.helloWorld());
        } catch (NamingException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            System.exit(1);
        }
        System.out.println("Exiting...");

    }

}

When executing said project (remember, the Glassfish is still running), you can see the following in the log of Glassfish:

INFO: ACDEPL103: Java Web Start services started for the app client HelloWorldClient (contextRoot: /HelloWorldClient)
INFO: HelloWorldClient was successfully deployed in 85 milliseconds.

And the log of your java client, should show the following indicating success:

Copying 1 file to /home/mrbear/NetBeansProjects/HelloWorldClient/dist
Copying 2 files to /home/mrbear/NetBeansProjects/HelloWorldClient/dist/HelloWorldClientClient
Warning: /home/mrbear/NetBeansProjects/HelloWorldClient/dist/gfdeploy/HelloWorldClient does not exist.
Starting...
Establishing connection to the bean...
Calling method on the bean...
Result: Hello, world.
Exiting...

Now this is just the basics, but it is always good to start from a simple example that works, and then branch out from there. Good luck!

I plan to keep this article updated with new versions of software that are issued, and with new expansions, like adding an ORM to your little bean.

Remarks

I've chosen for Netbeans 7.0.1, as there is an issue with automatic downloading of Glassfish 3.1 in Netbeans 6.9

In order for the java client to connect to the Glassfish when the Glassfish is not conveniently started by the Netbeans on your local machine, you need to change the settings used to connect to the remote host. This can be done programmatically using a Properties java hashmap thing, or you can use the dreaded jndi.properties file. I guess that last one could use a blog entry all on its own. [1]

I've not mentioned anything about setting up Glassfish on your local machine, as Netbeans basically does all that for you. You just need to select the little checkbox with "Download Glassfish" when creating a new Java EE Application Project.

It is a pleasure to work with Netbeans and Glassfish, basically because the two are nicely intertwined and setting up the environment is almost a point-and-click experience and speedily done. It makes it possible to spend more time developing and less time battling frameworks, fixing dependencies and installing jar-files.


Update


Ever since the coming of EJB 3.1, it is no longer necessary to have a WAR archive for your web related things, a JAR archive for your Enterprise Java Beans, and an EAR archive containing these two. If you are not interested in keeping these two strictly apart (in the name of modularization), you can just toss all your EJBs into the same WAR and deploy that WAR in EJB 3.1.

It simplifies life tremendously.

References


[1] How do I access a Remote EJB component from a stand-alone java client?
http://glassfish.java.net/javaee5/ejb/EJB_FAQ.html#StandaloneRemoteEJB

Thursday, 29 September 2011

Weird if statement

I found the following if statement a long long time ago.

// determine if c lies between a and b
if (c == a || c == b || (c > a && c < b))
{
    doStuff();
}

Refactor.

Wednesday, 28 September 2011

Weird use of Conditional Operator

Found this gem in my companies code today.

It is not exactly that it is wrong, strictly speaking, it's just... well, you can probably guess yourself what I would rather see here.

public boolean checkIfWeHaveState() 
{
    return state != null ? stateDao.countStates(state) > 0 : false;
}

P.S. off the top of my head, the only reason why I would ever do something like the above, is if Java doesn't do Short-circuit evaluation (for example with the & operator).

Of course, the following example is often used, and here a conditional statement is warrented.

public int getRowCount() 
{
    return list != null ? list.size() : 0;
}

Of course, these are but very small issues in the grand scale of things, but it was Sherlock Holmes who said “To a great mind, nothing is little.”

Wednesday, 14 September 2011

Addendum on Post "Decrease Indentation"

This is a small addendum to my post on Decrease Identation

I noticed that the same thing can be done in for-loops and the like, by means of continue. I just don't know if it's in common use at the moment.

Bad example:
/**
 * Process the proper states.
 */

public void processStates()
{
    List<State> stateList = new ArrayList<State>();
   
    for (State state : stateList) 
    {
        if (!state.equals(State.INVALID))
        {
            Capital capital = State.getCapital();
            if (capital != null && capital.size() > 1000000)
            {
                stateList.add(state);
            }
        }
    }
    stateService.processStates(stateList);
    refresh();
}

Good example (bad example refactored):
/**
 * Process the proper states.
 */

public void processStates()
{
    List<State> stateList = new ArrayList<State>();
   
    for (State state : stateList) 
    {
        if (state.equals(State.INVALID))
        {
            // invalid state!!!
            continue;
        }
        Capital capital = State.getCapital();
        if (capital == null || capital.size() <= 1000000)
        {
            // capital doesn't exists or not impressive enough!
            continue;
        }
        stateList.add(state);
    }
    stateService.processStates(stateList);
    refresh();
}

Tuesday, 2 August 2011

The Law of Leaky Abstractions

Found an url of Joel Spolsky called The Law of Leaky Abstractions.

In short: we're busy with abstracting everything away, so we can get things done quicker and on a bigger scale. Negative: if something goes wrong, we'll have no knowledge of what is wrong and where it's wrong and it will take a tremendous amount of time to solve the problem.

This problem will get bigger and bigger as time (and abstractions) goes on.

Monday, 25 July 2011

Error: PersistenceExceptionorg.hibernate.exception.GenericJDBCException: Cannot open connection

This problem has been causing me headaches, lately. After some heavy googling, I came across the following explanation.

The biggest problem here is that at first glance in my stacktrace it totally looked like a transaction/sqlserver problem.

Here's the stacktrace:

2011-07-23 22:23:46,805 WARN [org.hibernate.util.JDBCExceptionReporter] [ ] SQL Error: 0, SQLState: null 2011-07-23 22:23:46,805 ERROR [org.hibernate.util.JDBCExceptionReporter] [ ] Transaction is not active: tx=TransactionImple < ac, BasicAction: 53f73f9b:8b5:4e26e1da:501d3a status: ActionStatus.ABORT_ONLY >; - nested throwable: (javax.resource.ResourceException: Transaction is not active: tx=TransactionImple < ac, BasicAction: 53f73f9b:8b5:4e26e1da:501d3a status: ActionStatus.ABORT_ONLY >) 2011-07-23 22:23:46,805 ERROR [nl.isaac.youw8.ejb.StorageServiceBean] [ ] Error: PersistenceExceptionorg.hibernate.exception.GenericJDBCException: Cannot open connection searching an DashboardUser Query: from DashboardUser WHERE id = :id ORDER BY ID DESC javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: Cannot open connection at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:629) at org.hibernate.ejb.QueryImpl.getSingleResult(QueryImpl.java:99) at nl.isaac.youw8.ejb.StorageServiceBean.findSingle(StorageServiceBean.java:673) at nl.isaac.youw8.ejb.StorageServiceBean.findSingleObjectLike(StorageServiceBean.java:136) at sun.reflect.GeneratedMethodAccessor778.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:112) at org.jboss.ejb3.interceptor.InvocationContextImpl.proceed(InvocationContextImpl.java:166) at youw8.interceptors.DefaultInterceptor.intercept(DefaultInterceptor.java:140) at sun.reflect.GeneratedMethodAccessor220.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.jboss.ejb3.interceptor.InvocationContextImpl.proceed(InvocationContextImpl.java:118) at org.jboss.ejb3.interceptor.EJB3InterceptorsInterceptor.invoke(EJB3InterceptorsInterceptor.java:63) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) at org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor.invoke(TransactionScopedEntityManagerInterceptor.java:54) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) at org.jboss.ejb3.AllowedOperationsInterceptor.invoke(AllowedOperationsInterceptor.java:47) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) at org.jboss.aspects.tx.TxPolicy.invokeInCallerTx(TxPolicy.java:126) at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:195) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:95) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:62) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) at org.jboss.aspects.security.RoleBasedAuthorizationInterceptor.invoke(RoleBasedAuthorizationInterceptor.java:166) at org.jboss.ejb3.security.RoleBasedAuthorizationInterceptor.invoke(RoleBasedAuthorizationInterceptor.java:115) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) at org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:77) at org.jboss.ejb3.security.Ejb3AuthenticationInterceptor.invoke(Ejb3AuthenticationInterceptor.java:110) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:46) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) at org.jboss.ejb3.stateless.StatelessContainer.localInvoke(StatelessContainer.java:240) at org.jboss.ejb3.stateless.StatelessContainer.localInvoke(StatelessContainer.java:210) at org.jboss.ejb3.stateless.StatelessLocalProxy.invoke(StatelessLocalProxy.java:84) at $Proxy157.findSingleObjectLike(Unknown Source) at youw8.services.exposed.webservices.rest.MeasurementsResource.addActivityMeasurement(MeasurementsResource.java:486) at sun.reflect.GeneratedMethodAccessor1608.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$ResponseOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:184) at com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:67) at com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:276) at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:133) at com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:83) at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:133) at com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:71) at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1171) at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1103) at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1053) at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1043) at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:406) at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:477) at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:662) at javax.servlet.http.HttpServlet.service(HttpServlet.java:803) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at youw8.services.exposed.oauth.provider.servlets.AuthorizationServlet.doFilter(AuthorizationServlet.java:259) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175) at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:182) at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:262) at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:856) at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:566) at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1508) at java.lang.Thread.run(Thread.java:619) Caused by: org.hibernate.exception.GenericJDBCException: Cannot open connection at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103) at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:29) at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:426) at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:144) at org.hibernate.jdbc.AbstractBatcher.prepareQueryStatement(AbstractBatcher.java:139) at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1547) at org.hibernate.loader.Loader.doQuery(Loader.java:673) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236) at org.hibernate.loader.Loader.doList(Loader.java:2220) at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2104) at org.hibernate.loader.Loader.list(Loader.java:2099) at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:378) at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:338) at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:172) at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1121) at org.hibernate.impl.QueryImpl.list(QueryImpl.java:79) at org.hibernate.ejb.QueryImpl.getSingleResult(QueryImpl.java:80) ... 75 more Caused by: org.jboss.util.NestedSQLException: Transaction is not active: tx=TransactionImple < ac, BasicAction: 53f73f9b:8b5:4e26e1da:501d3a status: ActionStatus.ABORT_ONLY >; - nested throwable: (javax.resource.ResourceException: Transaction is not active: tx=TransactionImple < ac, BasicAction: 53f73f9b:8b5:4e26e1da:501d3a status: ActionStatus.ABORT_ONLY >) at org.jboss.resource.adapter.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:95) at org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider.getConnection(InjectedDataSourceConnectionProvider.java:47) at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:423) ... 89 more Caused by: javax.resource.ResourceException: Transaction is not active: tx=TransactionImple < ac, BasicAction: 53f73f9b:8b5:4e26e1da:501d3a status: ActionStatus.ABORT_ONLY > at org.jboss.resource.connectionmanager.TxConnectionManager.getManagedConnection(TxConnectionManager.java:319) at org.jboss.resource.connectionmanager.BaseConnectionManager2.allocateConnection(BaseConnectionManager2.java:402) at org.jboss.resource.connectionmanager.BaseConnectionManager2$ConnectionManagerProxy.allocateConnection(BaseConnectionManager2.java:849) at org.jboss.resource.adapter.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:89) ... 91 more 2011-07-23 22:23:46,805 WARN [org.hibernate.util.JDBCExceptionReporter] [ ] SQL Error: 0, SQLState: null 2011-07-23 22:23:46,805 ERROR [org.hibernate.util.JDBCExceptionReporter] [ ] Transaction is not active: tx=TransactionImple < ac, BasicAction: 53f73f9b:8b5:4e26e1da:501d3a status: ActionStatus.ABORT_ONLY >; - nested throwable: (javax.resource.ResourceException: Transaction is not active: tx=TransactionImple < ac, BasicAction: 53f73f9b:8b5:4e26e1da:501d3a status: ActionStatus.ABORT_ONLY >) 2011-07-23 22:23:46,805 ERROR [nl.isaac.youw8.ejb.StorageServiceBean] [ ] Error: PersistenceExceptionorg.hibernate.exception.GenericJDBCException: Cannot open connection searching an Activity Query: from Activity WHERE id = :id ORDER BY ID DESC javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: Cannot open connection at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:629) at org.hibernate.ejb.QueryImpl.getSingleResult(QueryImpl.java:99) at nl.isaac.youw8.ejb.StorageServiceBean.findSingle(StorageServiceBean.java:673) at nl.isaac.youw8.ejb.StorageServiceBean.findSingleObjectLike(StorageServiceBean.java:136) at sun.reflect.GeneratedMethodAccessor778.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:112) at org.jboss.ejb3.interceptor.InvocationContextImpl.proceed(InvocationContextImpl.java:166) at youw8.interceptors.DefaultInterceptor.intercept(DefaultInterceptor.java:140) at sun.reflect.GeneratedMethodAccessor220.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.jboss.ejb3.interceptor.InvocationContextImpl.proceed(InvocationContextImpl.java:118) at org.jboss.ejb3.interceptor.EJB3InterceptorsInterceptor.invoke(EJB3InterceptorsInterceptor.java:63) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) at org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor.invoke(TransactionScopedEntityManagerInterceptor.java:54) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) at org.jboss.ejb3.AllowedOperationsInterceptor.invoke(AllowedOperationsInterceptor.java:47) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) at org.jboss.aspects.tx.TxPolicy.invokeInCallerTx(TxPolicy.java:126) at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:195) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:95) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:62) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) at org.jboss.aspects.security.RoleBasedAuthorizationInterceptor.invoke(RoleBasedAuthorizationInterceptor.java:166) at org.jboss.ejb3.security.RoleBasedAuthorizationInterceptor.invoke(RoleBasedAuthorizationInterceptor.java:115) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) at org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:77) at org.jboss.ejb3.security.Ejb3AuthenticationInterceptor.invoke(Ejb3AuthenticationInterceptor.java:110) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:46) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) at org.jboss.ejb3.stateless.StatelessContainer.localInvoke(StatelessContainer.java:240) at org.jboss.ejb3.stateless.StatelessContainer.localInvoke(StatelessContainer.java:210) at org.jboss.ejb3.stateless.StatelessLocalProxy.invoke(StatelessLocalProxy.java:84) at $Proxy157.findSingleObjectLike(Unknown Source) at youw8.services.exposed.webservices.rest.MeasurementsResource.addActivityMeasurement(MeasurementsResource.java:490) at sun.reflect.GeneratedMethodAccessor1608.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$ResponseOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:184) at com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:67) at com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:276) at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:133) at com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:83) at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:133) at com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:71) at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1171) at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1103) at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1053) at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1043) at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:406) at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:477) at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:662) at javax.servlet.http.HttpServlet.service(HttpServlet.java:803) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at youw8.services.exposed.oauth.provider.servlets.AuthorizationServlet.doFilter(AuthorizationServlet.java:259) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175) at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:182) at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:262) at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:856) at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:566) at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1508) at java.lang.Thread.run(Thread.java:619) Caused by: org.hibernate.exception.GenericJDBCException: Cannot open connection at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103) at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:29) at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:426) at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:144) at org.hibernate.jdbc.AbstractBatcher.prepareQueryStatement(AbstractBatcher.java:139) at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1547) at org.hibernate.loader.Loader.doQuery(Loader.java:673) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236) at org.hibernate.loader.Loader.doList(Loader.java:2220) at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2104) at org.hibernate.loader.Loader.list(Loader.java:2099) at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:378) at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:338) at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:172) at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1121) at org.hibernate.impl.QueryImpl.list(QueryImpl.java:79) at org.hibernate.ejb.QueryImpl.getSingleResult(QueryImpl.java:80) ... 75 more Caused by: org.jboss.util.NestedSQLException: Transaction is not active: tx=TransactionImple < ac, BasicAction: 53f73f9b:8b5:4e26e1da:501d3a status: ActionStatus.ABORT_ONLY >; - nested throwable: (javax.resource.ResourceException: Transaction is not active: tx=TransactionImple < ac, BasicAction: 53f73f9b:8b5:4e26e1da:501d3a status: ActionStatus.ABORT_ONLY >) at org.jboss.resource.adapter.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:95) at org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider.getConnection(InjectedDataSourceConnectionProvider.java:47) at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:423) ... 89 more Caused by: javax.resource.ResourceException: Transaction is not active: tx=TransactionImple < ac, BasicAction: 53f73f9b:8b5:4e26e1da:501d3a status: ActionStatus.ABORT_ONLY > at org.jboss.resource.connectionmanager.TxConnectionManager.getManagedConnection(TxConnectionManager.java:319) at org.jboss.resource.connectionmanager.BaseConnectionManager2.allocateConnection(BaseConnectionManager2.java:402) at org.jboss.resource.connectionmanager.BaseConnectionManager2$ConnectionManagerProxy.allocateConnection(BaseConnectionManager2.java:849) at org.jboss.resource.adapter.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:89) ... 91 more 2011-07-23 22:23:46,805 ERROR [youw8.services.exposed.webservices.rest.MeasurementsResource] [ ] error occured:null

The important part in the stack trace is: org.hibernate.exception.SQLStateConverter.handledNonSpecificException. This indicates that an exception occurred that was not handled correctly and somewhere along the line the problem was caught, the transaction was rolled back, and then the rest of the business logic started performing without having any longer a transaction context.

At least, it's probably something like that.

It turned out to be a NullPointerException.

Friday, 22 July 2011

Senior Java Developer Test

Found the following test on http://thedailywtf.com. It tickled my fancy. An interesting use for recursion.

Question 1
(a) What does the following function do?
(b) How could the function be improved?
(c) Rewrite the function with your suggested improvements.
public String funcX (String s) {
  if (s == null || s.length() == 1 || s.length() == 0) {
    return s;
  } else {
    return funcX(s.substring(1)) + s.substring(0, 1);
  }
}

Just a small javadoc addendum to clarify things:

public String substring(int beginIndex, int endIndex)
Returns a new string that is a substring of this string. The substring begins at the specified beginIndex and extends to the character at index endIndex - 1. Thus the length of the substring is endIndex-beginIndex.

Monday, 18 July 2011

Wednesday, 6 July 2011

Decrease Indentation

And when I talk about indentation, I mean nested if statements, another one of my pet peeves.

This specific refactoring is called: Replace Nested Conditional with Guard Clauses[1].

Preconditions (GuardClauses) are a great example of where it is okay to return early at the start of the function.

It is very convenient to prevent the ArrowAntiPattern.

Here a bad example:

public boolean getPayment(String a, Double b)
{
    boolean result = false;
    if (a != null && b != null && !a.equals("") && b >= 0.0)
    {
        User user = getUser(a);
        if (user != null && user.getAccountValue() >= b))
        {
            user.setAccountValue(user.getAccountValue() - b);
            return true;
        }
        else
        {
            log.debug("User account not found or insufficient funds.");
            result = false;
        }
    }
    else
    {
        log.debug("Bad values.");
        result = false;
    }
    return result;
}

Here a good example (bad example refactored):

public boolean getPayment(String a, Double b)
{
    // preconditions
    if (a == null || b == null)
    {
        log.debug("Null values");
        return false;
    }
    if ("".equals(a) || b <= 0.0)
    {
        log.debug("Bad values");
        return false;
    }
    User user = getUser(a);
    if (user == null)
    {
        log.debug("User account not found.");
        return false;
    }
    if (user.getAccountValue() < b)
    {
        log.debug("Insufficient funds.");
        return false;
    }
    user.setAccountValue(user.getAccountValue() - b);
    return true;
}

One important skill here is the proper negation of an expression. You'd be surprised how many people lack this skill.

References


[1] Refactoring - Improving the design of existing code
Martin Fowler