Tuesday, December 04, 2007

Java on Mac OS X

I posted elsewhere that I now own an iMac and am doing most of my Java development on it. The big problem with Java on Mac is that the JDK is pretty out of date. The official version that comes with Mac OS X 10.4 Tiger is 1.5.0_07. This version seems buggy, as the JVM seems to hang when running test cases for one of my projects. I was getting quite frustrated, and in the end decided to run my test cases under OpenSolaris, which I installed as a VM using VMWare Fusion.

Fortunately, Apple has recently made available a pre-release version 1.5.0_13 from its Developer Connection web site. You need to be registered to be able to download this release. The good news is that it fixes the bug that was causing my tests to hang the JVM. I think it has something to do with the java.util.concurrency classes. Ofcourse, if you don't use these, you would not have faced the problems I was facing.

The long gap between the Java releases on Mac seems unacceptable, especially since the JDK is so buggy. The other problem is the lack of support from major vendors for the Mac platform. I would have liked to install and use IBM WebSphere and Rational products on my Mac, but it isn't amongst the supported platforms. Linux has much better support now-a-days.

Fast forward

It has been sometime since I last blogged about general programming topics. My day job has kept me from the joys of exploring the JPA. But many other things have happened to me in the meantime, life just goes on, and there is never enough time to catch up on everything.

For a start, I want to retitle this blog, by removing the Java from it. Let this just be a Programmer's Blog.

Sunday, May 07, 2006

Creating Oracle DataSource in Glassfish

To setup an Oracle Datasource in Glassfish, follow these steps:

1. Copy the Oracle JDBC drivers to /glassfish/domains/domain1/lib/ext directory. You may need to change the directory /glassfish/domains/domain1 to match your installation of Glassfish and the domain name.

2. Start Glassfish.

3. Login to the admin interface and create a JDBC Connection Pool.
Delete all properties, and add following properties:
user - set this to Oracle userid
password - set this to Oracle password
URL - set this to the URL, example jdbc:oracle:thin:@localhost:1521:xe.
xa-driver-does-not-support-non-tx-operations - set this to true.
Test the connection pool using ping.

4. Create a JDBC DataSource using the Connection Pool.

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.

Thursday, February 23, 2006

More EJB 3.0

For the past few days I have been working on a number of things. I shall blog about them in more detail when I have some time, but in the meantime, here is a summary:

1. Packaging issues. EJB 3.0 brings hassle-free packaging, however, it is still not easy to understand what the rules are. A discussion on packaging issues can be found here and here.

2. Semantics of merge() and persist() and how they are implemented in Glassfish is being discussed here.

3. Does EJB live up to its promise to bring POJO style programming to J2EE? I previously blogged about the fact that EJB 3.0 Entities are not really POJOs because they contain hidden semantics. See here for a discussion of dependency injection of EJBs and whether it is possible to implement Business Logic as POJOs.

Wednesday, February 15, 2006

Sharing attributes across Entities

One way to share common attributes across entities is to use inheritance, and put the common attributes in a super class. Another way is to abstract the common attributes into a separate Embeddable class and then embed it within the regular Entity classes. The latter approach has been used for some of the entities in the EJB3Demo project.

The entities Customer, District and Warehouse all contain some very similar columns for storing address information. I created a new class called Address to hold this common data. The Address class is marked as @Embeddable and contains the getters/setters for the attributes. Here is an extract:
@Embeddable public class Address implements Serializable {
String street1;
String city;
@Column(length=20)
public String getCity() {
return city;
}
@Column(length=20)
public String getStreet1() {
return street1;
}
}
Note that the getters have been annotated using @Column - this is useful for capturing the bits that are shared across the entities.

When you embed the Address object within an Entity, you can fine-tune the column mapping. Example:
@Entity
public class Customer {
Address address;
@Embedded
@AttributeOverrides({
@AttributeOverride(name="street1", column=@Column(name="C_STREET_1")),
@AttributeOverride(name="city", column=@Column(name="C_CITY")),
})
public Address getAddress() {
return address;
}
}
The getter for the Address object is decorated with the @Embedded annotation. The address object can be shared amongst multiple entities, and each entity can define its own column names, etc.

When you access embedded objects in EJBQL, you use the property name in the Query statement. For example, to access the city field in Customer, you would write:
SELECT c.address.city FROM Customer c
This syntax is also used when you have relationship mappings. For example, a District belongs to a Warehouse, and hence the District object contains an instance of the Warehouse object. To access the fields within Warehouse, you would write:
SELECT d.warehouse.name FROM District d
Although one could use inheritance to model above, I prefer to use the Embeddable class option as it more accurately reflects what is happening here. A Customer is not an instance of Address - a Customer has an Address. In this situation, Has-A relationship is more natural than Is-A relationship.

EJB3Demo project

I have started a new project at www.java.net. The goal of this project is to try out various features of Java EE 50, such as EJB 3.0, JAX-WS, JAXB, etc., and identify design/code patterns that result in:
  1. Improved portability and reusability of code, in particular, allow Business Logic and Data Access logic to be deployed inside and outside J2EE containers.
  2. Better separation of concerns while exploiting new persistence features of EJB 3.0.

I hope to blog about some of this stuff soon - stay tuned. In the meantime, I would welcome anyone who would like to contribute to the project.

The source code for the project is available for download from https://ejb3demo.dev.java.net/servlets/ProjectDocumentList.

Monday, February 06, 2006

Reusability of Code

I have given up trying to get the TPCC schema work as defined, i.e., using composite keys. Glassfish at present does not support Id Generators with composite keys, which poses a problem, as it means writing extra code for generating keys. As a workaround to this issue, I have modified the schema to use surrogate primary keys.

EJB persistence design favours Entity Relationships based upon surrogate primary keys.

One of the great benefits of EJB 3.0 is that it gets rid of all the boiler plate EJB code, allowing you to code Entity and Session beans as if they were POJOs. This raises the expectation that in this new world, it should be possible to write reusable code that is environment agnostic. By this I mean that I should be able to reuse my J2EE Business Logic classes and the Persistent classes in a J2SE or Servlet Container (Tomcat) environment without having to change any code.

There is an immediate stumbling block to achieving this, however. The unfortunate decision to introduce a new abstraction for Transaction Management for J2SE environment means that tranaction management code is not portable. The first rule for writing reusable code therefore is to avoid transaction management code in your classes. I will report on other pitfalls as I progress with my attempts to create reusable code.