Wednesday, March 29, 2006

Oracle JDeveloper as JSF Editor

After trying out various IDEs for editing Java Server Faces (JSF) files, I have finally settled on Oracle's JDeveloper as the best tool for the purpose. I had assumed that JDeveloper would insist on using ADF, but found to my pleasant surprise that it also allows you to design standard JSF pages in a visual manner. Unlike Sun Java Studio Creator which creates its own backing bean class, JDeveloper gives you full control, and lets you decide whether you want all/some/none of your UI components to be in your backing bean.

The Java IDE marketplace is such that no single tool meets all your needs. I find Eclipse is good for general purpose Java programming but not much use for J2EE stuff. Netbeans doesn't work for me - I have tried to use it several times but each time I have given up in frustration because I either cannot resolve some wierd error, or cannot get the IDE to do something simple. To give you an example, I try to edit a JSF file in Netbeans, and it will show code completion for jsp tags, but not for JSF. I don't have the time to work out why.

Thursday, March 09, 2006

Servlets and dependency injection

There is a very useful thread at the Glassfish discussion forum on the why it is not a good idea to use dependency injection to obtain references to EJBs or EntityManagers in Servlets.

Remote or Local interface?

EJB 3.0 takes away much of the pain associated with maintaining the Local and Remote interfaces for Session Beans. However, there are still some issues that you need to be aware of.

By design, the EJB specification disallows the same Business interface to be marked as @Local as well as @Remote (this restriction has been added in a revision to the PFD). The reason for this is that remote interfaces have different semantics to local interfaces, and it is usually inappropriate for the same method to be exposed as a remote interface as well as local interface. The problems are two-fold:

1. Remote interfaces must typically be designed to be coarse-grained.
2. Remote interfaces do not support the pass-by-reference semantics of parameter passing as in local interfaces.

Having separate Remote and Local interfaces forces designers to think about how the interfaces will be used and ensure that the design is optimised for the use case. It also reduces the chances of errors caused by incorrect semantics, such as clients relying upon ability to pass parameters by reference.

A drawback to this approach is that it does not allow transparent redeployment of an EJB from a co-located environment to a distributed environment or vice-versa. While such re-deployment has its dangers, there are times when it can prove useful to have such a facility.

Ideally, you should define your Session beans to have either remote or local interface. This will keep the design simple and allow you to implement Business Logic as POJOs.

If you do want to endow the same Session Bean with both remote and local interfaces, then, I suggest that you use the following example as a model:
public interface CustomerService {

void createCustomer(District d, Customer c);
void removeCustomer(Long id);
List findByDistrict(District d);

@Remote
public interface IRemote extends CustomerService {
}

@Local
public interface ILocal extends CustomerService {
}
}
Note that the local and remote interfaces extend a common business interface. Also note that the local and remote interfaces are nested within the business interface. I like this model because it reduces the clutter, keeps related interfaces together, and eases understanding.

When using dependency injection, you can specify explicitly whether you want the remote or local interface. For example:
@EJB(beanInterface=services.DistrictService.IRemote.class)
public final void setDistrictService(DistrictService districtService) {
this.districtService = districtService;
}

I also suggest that when specifying dependency injection, always annotate your setters rather than instance variables. This will allow you to use your beans outside the J2EE container, for example in a Spring Framework environment.

EJB 3.0 Packaging - Entities

I am looking at the various EJB 3.0 packaging options and trying to determine best practice. My first recommendation is that you should create separate projects for your entities and package your entities in independent jar files. This is important for a number of reasons.

Firstly, you will want to share your entities in multiple projects, so having them maintained independently makes it easier to share them across projects.

Secondly, the teams that define the entities are probably going to work closely with the folks that are responsible for defining the database Entity Model. It will be easier if these teams can work independently from other teams.

Last but not least, it is not possible to define Entities in a portable manner. The main portability issues are with the way Surrogate Keys are generated using Sequence Generators. Having separate projects for your entities will allow you to create drop-in replacements for different database vendors. So you can have one set of entities for Oracle, another for Apache Derby, and so on. For an example of this, please have a look at the EJB3Demo project.

When you create your application archives, place the Entity jar files in the lib sub-directory within the archive. This will ensure that the entity definitions are available to all your EJBs and Web applications within the application. This article by Sahoo explains the benefits of putting your entity jar files in the lib directory.