Friday, January 27, 2012

Sneak peak at Java EE 7 - Multitenant Examples with EclipseLink


The Aquarium is a great source of inspiration and most recent information about Java EE progress across all relevant specifications and reference implementations. They picked up a presentation by Oracle's Shaun Smith (blog/twitter) about the status and future of EclipseLink as an open source project. He covers all the new features which are going to be in EclipseLink 2.4 which will be availabke along with the June Eclipse Juno Release. In detail these are REST, NoSQL and Multitenancy. (details refer to the complete slide-deck (PDF) from the marsjug event.)
I like to see that EclipseLink still is the center of innovation in Java persistence and they are trying hard to adopt latest buzz timely. Working for a more conservative industry in general the main new feature I am looking for is multitenancy. What you can guess from the slides is, that something in this field should already be working with latest EclipseLink 2.3.0.

What is Multitenancy going to look like?
Let's start looking at what Oracle's Linda DeMichiel announced at last years JavaOne (compare blog-post) and also let's look at what the early draft (PDF) of the JPA 2.1 specification has to offer. The easier part is the early draft. Not a single line mentions "Multitenan[t|cy]" in any context. So, this is obviously still a big to do for further iterations. A bit more could be found in the JavaOne Strategy Keynote (Slides 41,42) and the JavaOne Technical Keynote (PDF) (Slide 25). The general Java EE 7 approach will be to have support for separate isolated instances of the same app for different tenants. The mapping should be done by the container and be available to apps in some way. This is all very vague until today and the only concrete code examples available from the slides refer to some obvious JPA related examples using two annotations @Multitenant and @TenantDiscriminatorColumn. Hmm. Doesn't this look familiar to you?

What is possible today?
It does! EclipseLink (as of 2.3.0 - Indigo) supports shared multitenant tables using tenant discriminator column(s), allowing an application to be re-used for multiple tenants and have all their data co-located. All tenants share the same schema without being aware of one another and can use non-multitenant entity types as per usual. But be aware of the fact, that this is only one possible approach to multitenancy for data. This is commonly referred to as "dedicated database" because all tenant's data go into one single db! The basic principles for the following are:
- application instances handle multiple tenants
- caching has to be isolated for every tenant by JPA
You can look at all the details on a dedicated EclipseLink wiki page. Want to give it a test drive? let's start. Prerequisites as usual (NetBeans, GlassFish, MySQL, compare older posts if you need more help.). Make sure to have the right EclipseLink dependencies (at least 2.3.0)! Create a new entity via the wizard, setup your datasource and persistence.xml and call it e.g. Customer.
@Entity
public class Customer implements Serializable {
//...
}
If you start your app you see EclipseLink creating something like this in your database.
Let's make this a multitenant entity. Add the following annotations:
@Entity
@Multitenant
@TenantDiscriminatorColumn(name = "companyId", contextProperty = "company-tenant.code")
public class Customer implements Serializable {
//...
}
There are multiple usage options available for how an EclipseLink JPA persistence unit can be used in an application with @Multitenant entity types. Since different tenants will have access to only its rows the persistence layer must be configured so that entities from different tenants do not end up in the same cache. If you compare the detailed approaches (Dedicated PC, PC per tenant, PU per tenant) in more detail, you see, that as of today you end up having two possible options with container managed injection of either the PC or the PU. Let's try the simplest thing first.

Dedicated Persistence Unit
In this usage there is a persistence unit defined per tenant and the application/container must request the correct PersistenceContext or PersistenceUnit for its tenant. There is one single persistence unit and nothing is shared. Go with the above example and add the following property to your persistence.xml:
<property name="company-tenant.code" value="TENANT1" />
Give it a try and compare the tables.
As you can see, you now have your companyId column. If you insert some data it will always be filled with the property value you assigned in the persistence.xml. Use either a  @PersistenceContext or a  @PersistenceUnit to access your entities. Using this approach you have a shared cache as usual for your application.

@PersistenceContext with Shared Cache (Source: S.Smith)

Persistence Context per Tenant
If you don't want to have a single tenant per application you could decide to have a single persistence unit definition in the persistence.xml and a shared persistence unit (EntityManagerFactory and cache) in you application. In this case the tenant context needs to be specified per EntityManager at runtime. In this case you have a shared cache available for regular entity types but the @Multitenant types must be protected in the cache. You do this by specifying some properties:
@PersistenceUnit
EntityManagerFactory emf;
Map props = new HashMap();
props.put("company-tenant.code", "TENANT2");
props.put(PersistenceUnitProperties.MULTITENANT_SHARED_EMF, true);
EntityManager em = emf.createEntityManager(props);

Shared @PersistenceUnit per tentant (Source: S.Smith)

Discriminator Approaches
The above examples work with a single discriminator tenant column. You can add the discriminator column to the PK by specifying a primaryKey attribute like the following:
@TenantDiscriminatorColumn(name = "companyId", contextProperty = "company-tenant.code", primaryKey = true)
It's also possible to have multiple tenant discriminator columns using multiple tables if you do something like this:
@Entity
@SecondaryTable(name = "TENANTS")
@Multitenant
@TenantDiscriminatorColumns({
    @TenantDiscriminatorColumn(name = "TENANT_ID", contextProperty = "company-tenant.id", length = 20, primaryKey = true),
    @TenantDiscriminatorColumn(name = "TENANT_CODE", contextProperty = "company-tenant.code", discriminatorType = DiscriminatorType.STRING, table = "TENANTS")
})

This leads to a secondary tenants table.


Additional Goodies
As always you can do the complete configuration within your persistence.xml only, too. For a reference please look at the already mentioned wiki page. One last thing is of interest. You could also map the tenant discriminator column with your entity. You simple have to make sure it isn't updated or inserted.
 @Basic
    @Column(name = "TENANT_ID", insertable = false, updatable = false)
    private int tenantId;

    public int getTenantId() {
        return tenantId;
    }
Looking at the debug output you can see what is happening behind the scenes:
INFO: Getting EntityManager
INFO: Inserting Test Customer 
FEIN: INSERT INTO CUSTOMER (ID, TENANT_ID) VALUES (?, ?)
 bind => [1, 2]
FEIN: INSERT INTO TENANTS (ID, TENANT_CODE) VALUES (?, ?)
 bind => [1, TENANT2]
FEIN: SELECT t0.ID, t1.TENANT_CODE, t0.TENANT_ID, t1.ID FROM CUSTOMER t0, TENANTS t1 WHERE (((t1.ID = t0.ID) AND (t1.TENANT_CODE = ?)) AND (t0.TENANT_ID = ?))
 bind => [TENANT2, 2]

Curious for more Java EE 7 and JPA 2.1 goodies? Keep updated with the development status wiki page for the EclipseLink JPA 2.1 project.

Thursday, January 26, 2012

New Article in German iX Magazin. Time and Money in Java.


This is my first published article this year. The German iX magazin published an article of mine about the pitfalls of Java's time and money features.

Temporary employment
Time and currency calculations in Java
Dealing with time and currency formats in Java is complicated, difficult to handle, and thus a potential source of error. Only those, who  know the pitfalls of using standard APIs and frameworks are on the safe side.

This is a German article and you can either grab the latest issue online or buy it at your favorite kiosk.

If you like, you can check out some other articles of mine. Some of them done in English, too. You just need to search this blog for posts, labeled "article" and you get some results. [UPDATE 29.01.2012]
The article is available for free online. Read it now: http://www.heise.de/ix/artikel/Zeitarbeit-1416759.html

Monday, January 23, 2012

The Heroes of Java: Trisha Gee


The 11th part of my "Heroes of Java" interview series. Thanks for following it! Stay tuned for the next parts!

Trisha is a developer at LMAX, the London Multi Asset eXchange. She's been working in financial markets for the last 5 years or so, but a fear of boredom and healthy amount of job-hopping before then has given her a wide breadth of experience, in a range of industries, over the 10+ years she's been a professional developer. Currently trying to get her head around low-latency, high performance coding whilst also keeping her fingers in the other pies LMAX has to offer, such as continuous delivery and agile. Trisha is heavily involved in the London Java Community and the Graduate Development Community, she believes we shouldn't all have to make the same mistakes again and again.

General part
Who are you?
I'm Trisha - Java developer; geek; triathlete; photographer and socialite. I love problem-solving but I'm more fascinated by people and how teams, groups, companies and societies work, which is why I'm involved in the London Java User Group, and it's what draws me to the conference scene.

Your official job title at your company?
Senior Developer

Do you care about it? 
To some extent. At my company I'm the driving force behind evangelising the awesome technical stuff we've done and I'm heavily involved in our recruitment process, but I wanted to make sure my title was "developer" rather than anything more fluffy or more grand. I feel I won't be taken seriously by the technical community if I'm not an actual, proper developer.

Do you speak foreign languages? Which ones?
I learnt French at school but I'm very bad at it.

How long is your daily "bootstrap" process? (Coffee, news, email)
If you include all the time between waking up and actually starting "real" work, I guess we're talking nearly 4 hours! - First thing I do when I wake up is check my e-mail on my phone. This is a terrible habit I would like to break, because I have no intention of actually replying to anything and it just slows me down - Coffee and breakfast at home followed by the gym or a run. I can't function properly without some sort of physical exercise in the morning. - Then there's all the rubbish of getting ready for, and getting into, work. Since I'm usually thinking about what I'll be working on that day, and what my schedule is like, I think of this as part of the bootstrap. - Second coffee at work, during which time I catch up on e-mail & my RSS feeds, and check up on things like the status of test results in our continuous delivery pipeline. This usually takes from when I get in to our morning standup at 9:45 

Twitter
You have a twitter handle? Why?
Yes, I'm @trisha_gee. Originally I posted to it like a Facebook status update, because I never really posted anything on FB that I wouldn't make public. I still use it for that a bit - I like to be flippant on twitter, but I tend to be more technology focussed on there than I used to be. I link to interesting stuff I've stumbled over and to my blog posts and material related to me (of course!). I had a Twitter revelation at JAX London this autumn though, I found it very useful for engaging in conversations about the presentations or subjects at a conference, and it helps to bridge the gap between you and people you've never met before at these events. Since then I use it much more conversationally.

Whom are you following in general?
I'm terrible, I mostly use it to publish rather than subscribe - I write a lot to it but only dive in to read occasionally. I follow a lot of techies - my fellow London Java Community guys; a lot of people I've met at conferences; and a lot of people who seem to have found me via my blog, including a network of awesome women programmers. I also use it to get the odd bit of info about photography or sports events, and London-based cool stuff. 

Do you have a personal "policy" for twitter?
Twitter is largely my professional-facing persona, if you like. But that's so much a part of who I am that I like to tweet the odd thing that gives an insight into me as a person. We're not automata, and I think any division between personal and professional is either artificial, or so blurry it's not really a division.

Does your company restricts or encourages you with your twitter ussage? 
Neither. My Twitter is useful for work because part of what I do is evangelism, but I'm not pushed to do it or given time for it. But then I'm not discouraged from it either. I have no idea what I would do if I was told not to do it any more!

Work
What's your daily development setup? (OS/IDE/VC/other Tools)
Ridiculous machine for coding on: Fedora Core 13, 24Gb of RAM, a pair of 4-core Xeon E5620 with HT enabled. - IntelliJ IDEA - SVN - Two monitors I always have Chrome, IntelliJ, Pidgeon and a terminal open. In Chrome, I always have Google Mail, Reader, Calendar and Groups open (I love the "pin tabs" functionality), along with my work webmail and my blog real-time stats (I'm a bit OCD). In another chrome window I have the "information radiator" of our build pipeline, which is usually open on my second monitor, and an additional tab for AutoTrish our tool that shows the intermittency in our acceptance tests. When I'm not at work, I have my MacBook Air, which I thought was a terribly frivolous purchase but turns out to be one of the best investments I have ever made. I was going to use it just for blogging, but it's powerful enough for development too.

Which is the tool providing most productivity to your work?
Hmm. Probably my team. My actual tools just distract me. 

Your prefered way of interacting with co-workers?
We pair program most days. If we (my pair and I) have a question we will talk face-to-face like real human beings to the person with the answer to that question. This is very odd to me, I prefer instant messenger, but this turns out to be the most effective way to get answers and allows you to ask questions you didn't even know you had. Most of the technology department has lunch together in our kitchen on most days. I love this, we feel like we're in it together, we get to blow off steam and find out what the other teams are working on. We also get some insight into what's going on outside of day-to-day development, as a lot of those who count as "management" are there too.

What's your favorite way of managing your todo's?
I used to like lists in my notepad (always written in pencil). But because we pair program and rotate around the stories that are in play, I try and capture tasks on post-it notes so that they can be added to the Kanban board. I tend to use my e-mail inbox as a todo list for things which are not directly related to the code I'm working on, and I have several calendars to track time-critical things. I even have a whiteboard at home for todo items and shopping lists. Did I mention I was a bit OCD?

If you could make a wish for a job at your favorite company: What would that be?
Somewhere I'm surrounded by smart people; a job/company that enables me to travel, and to meet people; a role that allows me time to think and experiment and write and present; and, of course, plenty of time to write actual, useful, code.

Java
You're programming in Java. Why?
I studied it at university so it made sense to take Java roles when I graduated in 2001. Previously I had worked with VB and Pascal and Basic, and web technologies like HTML and JavaScript. Object Oriented Design started to make sense to me, and I stuck with Java. I'm not particularly precious about it, but with 10+ years commercial experience, it's frustrating to work in anything more unfamiliar. The fascinating thing we've found at my company is that Java can be a language suitable for high performance code. This is the area that currently interests me, especially as Java actually tries to abstract away many concepts that you might traditionally worry about, like which CPU instructions are the fastest for achieving a particular goal. It's almost a game to get Java to do what you want. And at the end of it, you have code which is not only fast, but really very readable.

What's least fun with Java? 
UI programming. But I haven't had to do it for years because I always work on projects with web front ends or APIs.

If you could change one thing with Java, what would that be?
I was rather taken with C#'s closures. I guess lambdas are a step in that direction.

What's your personal favorite in dynamic languages?
Now you've got me. I haven't actually tried any for a long time. Is that heresy? I'll have to say JavaScript because it's the one I have most experience with.

Which programming technique has moved you forwards most and why?
I think probably Test Driven Development, in terms of a real game-changer in my own code. I started looking into it, and trying it out, about five years ago. In my current role I really got to refine it because we use tests all the way from the unit level to acceptance (using our own DSL) and performance. The thing I've been working on most this last year is improving my Domain Driven Design. TDD can drive to you local optimisations, and can, if you're not careful, lead to losing the big picture. By thinking about the whole domain, modelling it (even if it's just scribbles on a white board) and having a ubiquitous language with the business, you should be able to write cleaner, clearer, more maintainable and extensible code.

What was the biggest project you've ever worked on?
In my early career I did not have enough knowledge of the overall architecture to absorb how big or small a project was. At Ford Motor Company, and at one of the investment banks, I worked on a number of large enterprise projects with teams of a dozen or more programmers on the section I was working on. Looking back, I think the complexity was integration rather than it being some massive application with huge amounts of functionality. In terms of complexity and sheer range of functionality, the project I'm working on at the moment is probably the biggest. Our team is quite small (about 15 developers in the whole company), but we all work on all areas of the system, which includes the matching engine, the user interface, our four different APIs (including a C# one), administration tools, reporting... basically everything an FSA-authorised financial exchange needs to run its business. I believe that keeping the team small, and focussing on one area every milestone, has created a good, maintainable product and a team that is capable of continuing to build on it.

Which was the worst programming mistake you did?
When I was working for a retail bank I deleted two and a half (out of four) test environments 30 minutes before our Christmas lunch... It was lucky everyone was out for the lunch because it gave me a few hours to restore everything. Lesson learned? Always check the directory you're in before you type "rm -rf"...

Arquillian with NetBeans, WebLogic 12c, JPA and a MySQL Datasource


You probably followed my posts about testing more complex scenarios with embedded GlassFish (Part I / Part II). Next on my list of things to do was to get this setup working with latest WebLogic 12c.

Getting Started
Follow the steps in the getting started part of my first two posts. There are only a few things you have to change to get this working. Obviously you need a WebLogic 12c. Grep a copy from the OTN download-page. Read and accept the license and download either the ZIP installer or the full blown installer for your OS. Arun Gupta has a nice post about getting started with the ZIP installer. This basically is about downloading, extracting, configuring, creating your domain. Assume you have a domain1 in place. Make sure to copy the mysql-connector-java-5.1.6-bin.jar to domain1/lib and fire up the server by startWebLogic.cmd/.sh in your domain1 root directory. Next you need to configure the appropriate connection pool. You also could do this using some WLST magic or with the new WebLogic Maven Plugin but I assume you are doing this via the admin console. Go to Domain > Services > Data Sources and create a MySQL Datasource AuditLog with jndi name "jdbc/auditlog". Make sure the server is running while you execute your tests!

Modifying the sampleweb Project
Now open the sampleweb project's pom.xml and remove the glassfish-embedded-all dependency together with the arquillian-glassfish-embedded-3.1 and the javaee-api. Now add the wls-remote-12.1 container and the jboss-javaee-6.0 dependencies:

 <dependency>
            <groupId>org.jboss.arquillian.container</groupId>
            <artifactId>arquillian-wls-remote-12.1</artifactId>
            <version>1.0.0.Alpha2</version>
            <scope>test</scope>
  </dependency>
  <dependency>
            <groupId>org.jboss.spec</groupId>
            <artifactId>jboss-javaee-6.0</artifactId>
            <version>1.0.0.Final</version>
            <type>pom</type>
            <scope>provided</scope>
        </dependency>

Now open your arquillian.xml descriptor and change the container settings to use the wls container:
 
<container qualifier="wls" default="true">
        <configuration>
            <property name="adminUrl">t3://localhost:7001</property>
            <property name="adminUserName">weblogic1</property>
            <property name="adminPassword">weblogic1</property>
            <property name="target">AdminServer</property>
            <property name="wlsHome">X:\path\to\wlserver\</property>
        </configuration>

Make sure to use the right target server and point to the correct wlsHome. Right-click the AuditRepositoryServiceTest in NetBeans and run "Test File". You will see the remote container doing some work:

22.01.2012 22:40:34 org.jboss.arquillian.container.wls.WebLogicDeployerClient deploy
INFO: Starting weblogic.Deployer to deploy the test artifact.
22.01.2012 22:40:46 org.jboss.arquillian.container.wls.WebLogicDeployerClient forkWebLogicDeployer
INFO: weblogic.Deployer appears to have terminated successfully.
22.01.2012 22:40:53 org.jboss.arquillian.container.wls.WebLogicDeployerClient undeploy
INFO: Starting weblogic.Deployer to undeploy the test artifact.
22.01.2012 22:41:00 org.jboss.arquillian.container.wls.WebLogicDeployerClient forkWebLogicDeployer
INFO: weblogic.Deployer appears to have terminated successfully.

And the test going green! If you look at the domain log, you can see, that the test.war module is successfully deployed and undeployed.

Remarks and Thoughts
Looking at what we have with WebLogic 12c (especially the new maven plugin) this all seems very hand-crafted. What would a WebLogic developer have done prior to that in a maven based project? He would have pushed the weblogic.jar to his local repository and use it instead of using any jboss-javaee-6.0 or javaee-api dependencies. If you try this with the Arquillian wls container you start seeing some weird exceptions like the following:
Loading class: javax.transaction.SystemException
Exception in thread "main" java.lang.ClassFormatError: Absent Code
attribute in method that is not native or abstract in class file
javax/transaction/SystemException
This is basically because only the wlfullclient.jar contains all needed classes for remote management via JMX. The magic weblogic.jar does have some additional class-path entries in it's manifest which could not be resolved if you put it to your local m2 repository. So you simply have two options left. Use the wlfullclient.jar (see how to build it in the docs) for testing and the weblogic.jar for your development or stick to the jboss-javaee-6.0 dependency for development and testing (scope provided). Both are valid alternatives. As you can see, the WebLogic container is still undocumented in the Arquillian documentation. You can find a more detailed documentation looking at the wls-container project on github.
Download the simpleweb-wls.zip project as a reference to get you started.
Thanks to Vineet and Aslak for the help!

Wednesday, January 18, 2012

Review: "JBoss AS7 Configuration, Deployment and Administration" by Francesco Marchioni


Packt was so kind to hand their latest publication to me for a review. JBoss AS 7 Configuration, Deployment and Administration promises to give you an expert's understanding of the single components that makes up the JBoss application server. Showing you how to use them, helping you to cut down the learning curve for this exciting product and guide you through configuration, management, deployment and advanced administration of JBoss AS 7.

Abstract: As the Java EE standard has evolved and matured, the API has become increasingly rich and complex. The next generation of application servers needs to be modular and configurable to run only specific services or containers. JBoss AS 7 promises to meet those requirements but the configuration of a complex application server is composed of a mix of administrative and management tasks which often overlap, generating confusion.

JBoss AS 7 Configuration, Deployment and Administration will give you an expert's understanding of every component that makes up the JBoss application server, and will show you how to use them, helping you to dramatically cut down the learning curve for this exciting product.

This book will guide you through configuration, management, deployment and advanced administration in a logical order to avoid the common pitfalls of setting up a new AS. The book dives into the new application server structure and shows you how to install it. You will learn how to configure the core AS services, including thread pools, the messaging system, and the transaction service. Finally, you will learn how to deploy and manage your applications and then tune the performance of your AS to achieve an efficient, indispensible application server.

Book: JBoss AS 7 Configuration, Deployment and Administration
Language : English
Paperback : 380 pages [ 232mm x 186mm ]
Release Date : December 16, 2011
ISBN-10: 1849516782
ISBN-13: 978-1849516785

About the Author
Francesco Marchioni (@mastertheboss) is a Sun Certified Enterprise Architect employed by an Italian company based in Rome. He started learning Java in 1997, and since then he has followed the path to the newest Application Program Interfaces released by Sun. He joined the JBoss Community in 2000, when the application server was running the release 2.X.
He has spent many years as a software consultant, where he has overseen many successful software migrations from vendor platforms to open source products such as JBoss AS, fulfilling the tight budget requirements of current times.
Over the last five years, he started authoring technical articles for O'Reilly Media and running an IT portal focused on JBoss products (http://www.mastertheboss.com).

The Content
The book has 380 pages. Chapter one starts with page 26, chapter 11 sumary ends on page 333. That's not too much overhead and the main part actually cover good content.

Chapter 1 is about installing JBoss AS 7.
It gives a basic introduction to the new application server, depicting its most important features and shows how to install it on your machine.

Chapter 2 covers the Application Server's configuration.
Beside the main configuration file and some core parts of it, such as like the Thread pool configuration it also looks into the Logging subsystem.

Chapter 3, talks about configuring Enterprise Services
and dives into modeling the core Java Enterprise services using the standalone configuration file.

Chapter 4, covers the JBoss Web Server Configuration
and completes the standalone server configuration by looking at the Web subsystem. This chapter also covers a full Java EE example.

Chapter 5, is about the JBoss AS Domain configuration
and teaches the reader how to shape the domain server configuration and the criteria behind the choice of a standalone or domain server configuration. 

Chapter 6, Deploying Applications on JBoss AS
covers all the details of application deployment. A dive into class loading mechanism is also included.

Chapter 7, Managing the Application Server
Covers the related management tools used to control the application server instances.

Chapter 8, talks about Clustering 
All the AS 7 clustering capabilities that provide scalability and high availability to Java EE applications.

Chapter 9, Load Balancing Web Applications
Covers another concern of clustering, which is the ability to make several servers participate in the same service and do the same work.

Chapter 10, Securing JBoss AS 7
covers the foundation of JBoss Security framework and how to secure Enterprise applications and the server management interfaces.

Chapter 11, Taking JBoss AS 7 into the cloud
The mandatory chapter these days covers AS 7 and Red Hat OpenShift platform.

Writing and Style
The general writing is easy to follow, at least for non native speakers like me. I was also feeling very comfortable with the terms used through the book. So no big surprises if you are experienced in the Java EE area. Hints and extra information is placed at the suitable and helpful positions and I also like the examples (configuration and more) a lot. Most of the more complex stuff is additionally explained with images and concept drawings which is also very helpful.

Conclusion and recommendation
This book doesn't require any existing knowledge of AS7 and introduces you from the ground up. Nevertheless, there are hints about upgrading existing installations all over the book. So, it has a lot to offer for both experienced and beginners. The structure is good and beside the mandatory cloud chapter I really enjoyed reading and playing along with the examples. Also very appreciated is the fact that there is not too much Java EE source code in the book and the author really tries to focus on deployment and administration. So don't be afraid about having to read a complete Java EE 6 tutorial along the way. Another point to mention is, that this book is far more complete than any available online documentation today. Especially the clustering and load-balancing parts are very interesting to read and also cover the various load balancing mechanisms. You are with JBoss? Go with this book!

Arquillian with NetBeans, GlassFish embedded, JPA and a MySQL Datasource - Part II


This is a followup post to the one I did yesterday. Even if it was intended to be a more complex demo it turns out, that I missed a big issue with the setup. Everything works fine up to the point when you start introducing enhanced features to your entities. To name but a few: lazy loading, change tracking, fetch groups and so on. JPA providers like to call this "enhancing" and it is most often referred to as "weaving". Weaving is a technique of manipulating the byte-code of compiled Java classes. The EclipseLink JPA persistence provider uses weaving to enhance JPA entities for the mentioned things and to do internal optimizations. Weaving can be performed either dynamically at runtime, when Entities are loaded, or statically at compile time by post-processing the Entity .class files. Dynamic weaving is mostly recommended as it is easy to configure and does not require any changes to a project's build process. You may have seen some finer log output from EclipseLink like the following:
[...]--Begin weaver class transformer processing class [com/mycompany/simpleweb/entities/AuditLog].
[...]--Weaved persistence (PersistenceEntity) [com/mycompany/simpleweb/entities/AuditLog].
[...]--Weaved change tracking (ChangeTracker) [com/mycompany/simpleweb/entities/AuditLog].
[...]--Weaved lazy (ValueHolder indirection) [com/mycompany/simpleweb/entities/AuditLog].
[...]--Weaved fetch groups (FetchGroupTracker) [com/mycompany/simpleweb/entities/AuditLog].
[...]--End weaver class transformer processing class [com/mycompany/simpleweb/entities/AuditLog].

The problem with Arquillian and Embedded GlassFish
Imagine you take the example from yesterday's blog post and change the simple String account property to something like this:
 @ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
    private Person person;
That's exactly one of the mentioned cases where your JPA provider would need to do some enhancements to your class files before executing. Without modifying the project it would lead to some very nasty exceptions:
Exception Description: A NullPointerException would have occurred accessing a non-existent weaved _vh_ method [_persistence_get_person_vh].  The class was not weaved properly - for EE deployments, check the module order in the application.xml deployment descriptor and verify that the module containing the persistence unit is ahead of any other module that uses it.
[...]
Internal Exception: java.lang.NoSuchMethodException: com.mycompany.simpleweb.entities.AuditLog._persistence_get_person_vh()
Mapping: org.eclipse.persistence.mappings.ManyToOneMapping[person]
Descriptor: RelationalDescriptor(com.mycompany.simpleweb.entities.AuditLog --> [DatabaseTable(AUDITLOG)])
 at org.eclipse.persistence.exceptions.DescriptorException.noSuchMethodWhileInitializingAttributesInMethodAccessor(DescriptorException.java:1170)
 at org.eclipse.persistence.internal.descriptors.MethodAttributeAccessor.initializeAttributes(MethodAttributeAccessor.java:200)
[...]
indicating that something is missing. And that missing method is introduced by the weaving process. If you decompile a weaved entity you can see what the JPA provider is complaining about. This is how your enhanced entity class should look like. And this is only one of the enhanced methods a weaving process is introducing into your code.

  public WeavedAttributeValueHolderInterface _persistence_get_person_vh()
    {
        _persistence_initialize_person_vh();
        if(_persistence_person_vh.isCoordinatedWithProperty() || _persistence_person_vh.isNewlyWeavedValueHolder())
        {
            Person person1 = _persistence_get_person();
            if(person1 != _persistence_person_vh.getValue())
                _persistence_set_person(person1);
        }
        return _persistence_person_vh;
    }

Dynamic vs. Static Weaving
Obviously the default dynamic weaving doesn't work with the described setup. Why? Weaving is a spoiled child. It only works when the entity classes to be weaved do exist only in the application classloader. The combination of embedded GlassFish, Arquillian and the maven sure-fire-plugin mix this up a bit and the end of the story is, that exactly none of your entities are enhanced at all. Compare this nice discussion for a more detailed explanation. If dynamic waving doesn't work, we have to use the fallback called static weaving. Static means: post processing the entities during the build. Having the maven project at hand, this sounds like a fairly easy job. Let's look for something like this. The first thing you probably find is the StaticWeaveAntTask. The second thing may be Craig's eclipselink-staticweave-maven-plugin. Let's start with the StaticWeaveAntTask. You would have to use maven-antrunner-plugin to get this introduced. Copy classes from left to right and do an amazing lot of wrangling to get your classpath rigth. Laird Nelson did a great job to archetype-ize an example configuration for all 3 big JPA providers (EclipseLink, OpenJPA, Hibernate) and your could give this a try. A detailed explanation about what is happening can be found on his blog. Thanks Laird for the pointers! Don't get me wrong: This is a valid approach, but I simply don't like it. Mainly because it introduces a massive complexity to the build and having seen far too many projects without the right skills for managing even normal maven projects, this simply isn't a solution for me. I tried the static weaving plugin done by Craig Day.

Adding static weaving to simpleweb
So, let's open the pom.xml from yesterdays project and introduce the new plugin:
 <plugin>
     <artifactId>eclipselink-staticweave-maven-plugin</artifactId>
     <groupId>au.com.alderaan</groupId>
     <version>1.0.1</version>
          <executions>
             <execution>
                  <goals>
                    <goal>weave</goal>
                  </goals>
                  <phase>process-classes</phase>
             </execution>
           </executions>
      </plugin>
Done. Now your classes are weaved and if you introduce some logging via the plugin configuration you can actually see, what happens to your entity classes. The plugin is available via repo1.maven.org. The only issue I came across is, that the introduced dependency towards EclipseLink 2.2.0 isn't (or course) not available via the same repo, so you probably would need to build it for yourself with the right repositories and dependencies. You can get the source code via the plugin's google code page.
Don't forget to add the weaving property to your test-persistance.xml:

  <property name="eclipselink.weaving" value="static" />

[UPDATE: 19.01.2012]
Craig released a new 1.0.2 version of the plugin which solves the issues with the EclipseLink dependency. You now can simply include the needed EclipseLink version as a dependency to the plugin. Also needed is the correct EclipseLink maven repository. A complete example with a configured log level looks like this:
  <repository>
            <id>eclipselink</id>
            <name>Repository hosting the eclipselink artifacts</name>
            <url>http://www.eclipse.org/downloads/download.php?r=1&amp;nf=1&amp;file=/rt/eclipselink/maven.repo/</url>
        </repository>

[...]
  <plugin>
                <artifactId>eclipselink-staticweave-maven-plugin</artifactId>
                <groupId>au.com.alderaan</groupId>
                <version>1.0.2</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>weave</goal>
                        </goals>
                        <phase>process-classes</phase>
                        <configuration>
                            <logLevel>ALL</logLevel>
                        </configuration>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>org.eclipse.persistence</groupId>
                        <artifactId>eclipselink</artifactId>
                        <version>2.3.1</version>
                    </dependency>
                </dependencies>
            </plugin>

Tuesday, January 17, 2012

Arquillian with NetBeans, GlassFish embedded, JPA and a MySQL Datasource


This is an, let's call it accidental post. I was looking into transactional CDI observers and playing around with GlassFish embedded to run some integration tests against it. But surprisingly this did not work too well and I am still figuring out, where exactly the problems are while using the plain embedded GlassFish for that. In the meantime I switched to Arquillian. After I looked at the Arquillian 1.0.0.Alpha4 a bit more detailed last year, it was time to see, what the guys prepared for 1.0.0 final. Some stuff changed a bit and I was surprised to only find some basic examples on the net. That was the main reason I started writing this post. To have a more complete example of all the three technologies working together.

Getting Started
First of all, get yourself a fresh copy of latest NetBeans 7.1. It's out since a few weeks and it really looks good. If you like, you can download a copy of the Java EE version, which comes with latest GlassFish OSS Edition 3.1.1 pre bundled. Install it and fire it up. Also grep a copy of MySQL Community Edition and install it. Back in NetBeans, setup a new Maven Webapplication via the new Project Wizard. Let's call it "simpleweb" and we tell it to run on GF 3.1.1 (if you haven't done so, you should create a Services>Server>GlassFish instance before or do it during the project setup).

Implement your Application
Even if this isn't test-driven, I like to use this approach because I still believe, that this is the most common case you find out there in your projects. You have a lot of stuff ready to run and you are looking for some kind of automated integration tests. So, let's assume you have a very basic entity, we call it "com.mycompany.simpleweb.entities.AuditLog". You can create it with the NetBeans new Entity wizard. The third step during the Entity creation is the provider and database setup. Define a new Datasource and name it "jdbc/auditlog". As a connection specification use MySQL J driver and I assume you have a database up and running (let's assume this is called auditlog). Test the connection and finish the wizard.


If you are using the wizard, you get some free gifts. Beside the fact, that you now have your AuditLog entity in the source tree, you also find a META-INF/persistence.xml file in your src/main/resources and a glassfish-resources.xml in src/main/setup. This is needed later on, keep it in mind. Add some additional properties to your entity. For now I add "String account". And don't forget to define a Version field "Timestamp timestamp". And it's also nice to have a little named query to get a list of all AuditLogs
@NamedQuery(name = "findAllAuditLogs",
query = "SELECT OBJECT (e) FROM AuditLog e")

@Version
private Timestamp timestamp;

If you are using the wizard, make sure to check your pom.xml. The wizard is adding some eclipselink dependencies in scope provided, so this shouldn't make a big difference here. Next is to add a com.mycompany.simpleweb.service.AuditRepositoryService EJB. This should be responsible for all CRUD operations on the AuditLog entity.
Add some code to it to insert an AuditLog:
@PersistenceContext
private EntityManager em;

  public void writeLog(String account) {
        AuditLog log = new AuditLog();
        log.setAccount(account);
        em.persist(log);
    }
And some more code to find out the total number of entries in your table:
public int findAll() {
        TypedQuery<AuditLog> query = em.createNamedQuery("AuditLog.findAllAuditLogs", AuditLog.class);
        return query.getResultList().size();

    }
That's all for now.

Adding Basic Test Dependencies
Next we are going to add some very basic test dependencies. Open your projects pom.xml file and add the following sections for Arquillian to your project:
        
         
        <repository>
            <id>JBoss</id>
            <name>JBoss Repository</name>
            <url>https://repository.jboss.org/nexus/content/groups/public/</url>
        </repository>
    <dependencymanagement>     
         
        <dependencies>
            <dependency>
                <groupid>org.jboss.arquillian</groupid>
                <artifactid>arquillian-bom</artifactid>
                <version>1.0.0.Final-SNAPSHOT</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>
        </dependencies>
    </dependencymanagement>
    <dependencies>
        
        <dependency>
            <groupid>org.jboss.arquillian.container</groupid>
            <artifactid>arquillian-glassfish-embedded-3.1</artifactid>
            <version>1.0.0.Final-SNAPSHOT</version>
            <scope>test</scope>
        </dependency>
        <dependency>
        
            <groupid>org.jboss.arquillian.junit</groupid>
            <artifactid>arquillian-junit-container</artifactid>
            <scope>test</scope>
        </dependency>
    </dependencies>
Beside that, you also need the embedded Glassfish dependency.
        
        <dependency>
            <groupid>org.glassfish.extras</groupid>
            <artifactid>glassfish-embedded-all</artifactid>
            <version>3.1</version>
            <scope>test</scope>
        </dependency>
We also need the MySQL J driver:
        <dependency>
            <groupid>mysql</groupid>
            <artifactid>mysql-connector-java</artifactid>
            <version>5.1.18</version>
            <scope>test</scope>
        </dependency>

Configuring Arquillian
After we have all the needed dependencies in place, we need to further configure Arquillian. This is done via the arquillian.xml which has to be placed in the src/test/resources folder (you might need to create it outside NetBeans before) and should look like this:
<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian-1.0.xsd">
    <engine>
        <property name="deploymentExportPath">target/arquillian</property>
    </engine>

    <container default="true" qualifier="glassfish">
        <configuration>
            <property name="sunResourcesXml">src/main/setup/glassfish-resources.xml</property> 
        </configuration>
    </container>
</arquillian>
The engine parameter tells Arquillian to place a packaged version of your test archive to a target/arquillian folder. This is quite useful for hunting down problems. The container qualifier points the testrunner to the glassfish-resources.xml which was created by the entity creation wizard. All done. One single thing I would like to suggest is to make a copy of your persistence.xml and place it to the test/resources folder renamed to something like test-persistence.xml. I consider it a best practice to have an option to configure your test JPA a bit different than the productive one. To make a simple example, we would like to see some more logging output during the tests, so the copied version should additionally contain the needed parameters. I also like to change the table generation strategy for testing to drop-and-create-tables:
 
<property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
<property name="eclipselink.logging.level.sql" value="FINEST" />
<property name="eclipselink.logging.parameters" value="true" />
Let's take a look at the the tests.

Add a Testcase
Lets add a test. This is easy with NetBeans: Right click on your EJB and select "Tools>Create JUnit Tests". Select JUnit 4.x and accept the name proposal "com.mycompany.simpleweb.service.AuditRepositoryServiceTest". Now your project has a new "Test Packages" folder. As you can see, the test is in error. NetBeans assumes, that you want to do a test based on embedded EJBContainer. Nice guess, but we would like to add some Arquillian here. Remove the EJBContainer import and strip the class down to this:
@RunWith(Arquillian.class)
public class AuditRepositoryServiceTest {
}
Now it's time to define the deployment archive for the test using ShrinkWrap. The deployment archive for the test is defined using a static method annotated with Arquillian's @Deployment annotation.
@Deployment
    public static JavaArchive createTestArchive() {
        return ShrinkWrap.create(JavaArchive.class, "test.jar").addPackage(AuditLog.class.getPackage()).addPackage(AuditRepositoryService.class.getPackage()).addAsManifestResource(
                new ByteArrayAsset("<beans>".getBytes()),
                ArchivePaths.create("beans.xml")).addAsManifestResource(
                "test-persistence.xml",
                ArchivePaths.create("persistence.xml"));
    }
After the packages which should be contained are added, an empty beans.xml (which should be enough for now) is added and the test-persistence.xml is added as a manifest resource named persistence.xml. Great. One last thing is to define the test itself.
@EJB 
AuditRepositoryService repository;

 @Test
    public void insertLog() throws Exception {
        repository.writeLog("Markus");
        int numberOfLogs = repository.findAll();
        Assert.assertEquals(1, numberOfLogs);

    }

We are inserting a simple test entity and are getting the count back from the database which is checked via assertEquals. That's all. Fire up your tests. (Right click on the AuditRepositoryServiceTest class and select "Test File (Strg+F6).

Examining what's happening
The output window shows the Std.out of a starting GlassFish. If you examine the output further you see, that the JDBC connection pool and the JDBC resource are created:
INFO: command add-resources result: PlainTextActionReporterSUCCESSDescription: add-resources AdminCommandnull
    JDBC connection pool mysql_auditlog_rootPool created successfully.
    JDBC resource jdbc/auditlog created successfully.
and the "test" application was deployed:
INFO: WEB0671: Loading application [test] at [/test]
17.01.2012 10:12:39 org.glassfish.deployment.admin.DeployCommand execute
INFO: test was successfully deployed in 6.461 milliseconds.
Scanning through the output does point you to some EclipseLink stuff, but the additional sql logging doesn't seem to be in effect. This is because EclipseLink needs to know to which logger to point the output to. Normally the log output is redirected to the server logger which is auto-discovered. We didn't do any logging configuration until now and simply rely on what is default for Java Logging. So, let's add a little logging configuration. Put an empty logging.properties file to src/test/resources and add some simple lines to it:
handlers=java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.ConsoleHandler.level=FINEST
add the maven sure-fire plugin to the build section of your pom.xml:
 
<plugin>
                <groupid>org.apache.maven.plugins</groupid>
                <artifactid>maven-surefire-plugin</artifactid>
                <version>2.11</version>
                <configuration>
                    <includes>
                        <include>com/mycompany/simpleweb/service/*</include>
                    </includes>
                    <systempropertyvariables>
                        <java.util.logging.config.file>${basedir}/src/test/resources/logging.properties</java.util.logging.config.file>
                    </systempropertyvariables>
                </configuration>
            </plugin>
If you now issue a clean and build, you see, that the desired log output is shown in the NetBeans build output.
FEIN: INSERT INTO AUDITLOG (ID, ACCOUNT, TIMESTAMP) VALUES (?, ?, ?)
 bind => [1, Markus, 2012-01-17 11:02:54.0]
In fact, if you use Strg+F6 you still only see INFO level messages. To fix this, you need to change your NetBeans run action settings. Right click your project and select "Properties". Select "Actions" and "Test file". Add the following as a new line within "Set Properties" area:
java.util.logging.config.file=src/test/resources/logging.properties


Now you also see the desired log-level output with a single test-run. That was it. You can download the complete sample maven project (as ZIP-File) with the mentioned classes and play around a bit. Have fun!

[UPDATE: 18.01.2012]
Static weaving problem explained in another post.

Tuesday, January 10, 2012

Throwing Light on GlassFish Webserver Plugins and Proxying


Inspired by an article done by Lincoln Baxter III about running JBoss on port 80, I decided to have a more detailed look at what's possible and necessary for GlassFish to utilize proxying and load-balancing. 

Let's look at the basics front up. First of all we have to separate two kinds of problems here. The one addressed by Lincoln which talks about general Unix/Linux security restriction which prevents non-root users from binding to privileged-ports (in this case port 80). The second one is about load balancing and failover which is needed in clustered environments. Both can be solved with some kind of proxying approaches and depending on your needs you will have a couple of options to solve it.

Binding GlassFish to port 80 (HTTP)
There are occasions when it is convenient to allow non-root users to run services, binding to "privileged ports". There are several approaches to this problem.

Using a firewall(iptables) to redirect packets
This technique configures the firewall to send all port 80 traffic to port 8080 (Normal GF Application Port). You can do the same thing for any other ports you need that are less than 1024.

iptables -t nat -A PREROUTING -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 8080 
iptables -t nat -A PREROUTING -p udp -m udp --dport 80 -j REDIRECT --to-ports 8080 

Using authbind
Authbind is an Open source system utility. The authbind software allows a program that would normally require superuser privileges to access privileged network services to run as a non-privileged user. authbind allows the system administrator to permit specific users and groups access to bind to TCP and UDP ports below 1024. Authbind is distributed with the Debian and Ubuntu Linux distributions. For all other distributions you would have to install it manually. By executing the following with an installed authbind

touch /etc/authbind/byport/80 
chown glassfish:glassfish /etc/authbind/byport/80 
chmod 755 /etc/authbind/byport/80 

you will enable the "glassfish" user to bind to port 80 on your maschine.

Using Jsvc
Apache Commons Jsvc allows the application (e.g. GlassFish) to perform some privileged operations as root (e.g. bind to a port < 1024), and then switch identity to a non-privileged user. There two ways to use jsvc: via a Class that implements the Daemon interface or via calling a Class that has the required methods. Using this for GlassFish would mean to implement a Jsvc GlassFishDaemon Class which implements the needed Methods (init, start, stop, destroy) and run it via the

  ./jsvc -cp mygflauncher.jar GlassFishDaemon

Apache mod_proxy with ProxyPass
First step here is to have a running Apache which itself is already bound to port 80. Normally this is done via chroot environments or the sudo command. For a more detailed step-by-step guide look at Lincoln's post. This configuration allows remote servers to be mapped into the space of the local (Apache) server; the local server does not act as a proxy in the conventional sense, but appears to be a mirror of the remote server. The local server is often called a reverse proxy or gateway. All you need is the following directive, assuming that your Apache is running on port 80:

ProxyPass / http://localhost:8080/

For more details refer to the Apache documentation.

Apache mod_proxy with RewriteRules
If you are looking into more complex scenarios your are probably willing to redirect single contexts only. This is possible with the RewriteRule directive. It is the real rewriting workhorse. The directive can occur more than once, with each instance defining a single rewrite rule. The order in which these rules are defined is important - this is the order in which they will be applied at run-time.

ProxyPreserveHost on
RewriteEngine on

RewriteRule ^/exampleapp$ /exampleapp/ [R,L]
RewriteRule ^/exampleapp/(.*) http://localhost:8080/exampleapp/$1 [P,L]

Rewrite rule number one adds a eventually missing trailing slash and rule number two proxies your requests over to the Glassfish server. The ProxyPreserveHost directive makes sure that redirects work properly.

Methods for Load-balancing and Failover
In order to scale for large amounts of load, it is typical to use multiple server instances in enterprise environments. Typically a load balancer is used in front of these cluster of instances. There are several different approaches to load-balancing and failover. Here are a couple of software based ways which I have seen in the wild.

Oracle GlassFish LoadBalancer
Even if this is the first option you stumble across if you are looking around for load-balancing solutions, you have to keep in mind, that this is part of the commercial Oracle GlassFish Server and as such not free of charge. Even if it would be possible to use it with the OSS bits!
The Loadbalancer Plug-In is shipped as a ZIP bundle that you install after installing and configuring GlassFish Server and your desired web server. The plug-in is installed by means of a graphical GlassFish Loadbalancer Configurator that helps you configure your web server and GlassFish Server to work together. In most cases, the GlassFish Loadbalancer Configurator automatically configures GlassFish Server and your web server, and no manual intervention is required. However, depending on your web server configuration, there may be some manual configuration steps that you need to perform after installing the Loadbalancer Plug-In. This is also the case for Apache 2.2.x. You simple have to ensure some pre- and post-installation steps which can be found in details in the Oracle GlassFish server documentation. If you are interested in the inner workings of the plugin, you can have a look at the GlassFish LoadBalancer page which summarizes all the details. I assume they haven't changed that much for the latest version.

Apache mod_jk
Beside the official GlassFish LoadBalancer plugin which is part of the Oracle GlassFish server the recommended solution to load-balancing for the open source GlassFish is by using the Apache mod_jk. The Apache Tomcat Connector mod_jk can be used to connect the web container with the Apache HTTP Server. The configuration is a little more complex and you find tons of information about the configuration in general. First important step is to install the mod_jk into your Apache server. For a detailed step by step guide look at the official documentation. A minimal configuration looks like the following. Add the following lines to your httpd.conf:

LoadModule jk_module /home/oracle/glassfish3/apache/modules/mod_jk.so
JkWorkersFile /home/oracle/glassfish3/apache/conf/glassfish-workers.properties

# where to put the log files for the jk module
JkLogFile /home/oracle/glassfish3/apache/logs/mod_jk.log

# the log level [debug|info|error]
JkLogLevel info

# log format
JkLogStampFormat "[%a %b %d %H:%M:%S %Y]"

# options to indicate to send SSL KEY SIZE
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories

# set the request log format
JkRequestLogFormat "%w %V %T"

# send requests that contain the following to glassfish
JkMount /one-instance/* glassfish-worker1

# send requests to the cluster
JkMount /* loadbalancer


The JkWorkersFile contains all the needed information about your instances and the load-balancing.

# define the workers
worker.list=glassfish-worker1,glassfish-worker2,loadbalancer

# set properties for the workers
worker.glassfish-worker1.type=ajp13
worker.glassfish-worker1.host=localhost # your GlassFish instance1 host
worker.glassfish-worker1.port=24849 # your GlassFish instance1 port
worker.glassfish-worker2.type=ajp13
worker.glassfish-worker2.host=localhost  # your GlassFish instance2 host
worker.glassfish-worker2.port=24848  # your GlassFish instance2 port
worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=glassfish-worker1,glassfish-worker2


For a detailed guide for the configuration of Apache mod_jk with GlassFish 3.1 look at the official documentation or the excellent article from the middleware magic guys.

Last but not least you have to enable the JK Listener with each of your http-listeners via the GlassFish admin console and you have to add a jvmRoute system property by either using the asadmin command or adding it via the GlassFish admin console:

asadmin create-jvm-options "-DjvmRoute=worker1"

Apache mod_proxy_balancer
The Apache mod_proxy has a balancer extension called proxy_balancer_module. This module is highly configuratble and could be adopted to many szenarios. You can adjust the load balancing algorithms and stickyness and many other things. At a minimum your configuration looks like this:

ProxyPass / balancer://mycluster
<Proxy balancer://mycluster>
BalancerMember http://localhost:8080 route=route1
BalancerMember http://localhost:8080 route=route2
ProxySet stickysession=JSESSIONID
</Proxy>

To make sure the session sticks you will have to set a JVM option, add the following JVM option to your Glassfish instances so they know they are running in an Apache cluster setting:

asadmin create-jvm-options "-DjvmRoute=route1"


Note the jvmRoute needs to be the same as the route parameter mentioned in the BalancerMember entries (route1/route2).

Which way to go?
If you have different roads to travel your in charge of picking the right one. This isn't easy in general as every solution has it's strengths and weaknesses. Generally speaking you can rely on simply forwarding or proxying in most of the cases. Starting with development or testing stages. For most of the production sites I know you wouldn't stand the traffic without a cluster. With clustering comes loadbalancing into play. If you can go with the most basic round robin schemes available with the easier solutions you still have a quite simple setup. If you are forced to control your load and need to adjust it to different hardware sizes you better go with the load-balancing offer contained in the Oracle GlassFish server. Even if I know a lot of sites running the simpler mod_proxy_balancer or mod_jk approaches without any problems.
I am happy to read about your experiences!