Sunday, January 30, 2011

Running GlassFish with JRockit

Since GlassFish 3.0.1 the JDK support was extended. You now also could run GlassFish with Oracle JRockit 6 Update 17 R28.0.0+. This is a great choice in general and I must admit, that this announcement slipped through and missed my attention until today.

Getting started
Get the latest GlassFish 3.0.1 and the latest Oracle JRockit 28.1. Start with installing the JRockit to a suitable location. After that, start the GlassFish installer and do the same. Select the JRockit installation folder if you are asked to select the JDK. Finish the GlassFish installation. and change to %GF_HOME$/bin and type asadmin start-domain.
You will see something like this:
Waiting for DAS to start .Error starting domain: domain1.
The server exited prematurely with exit code 1.
Before it died, it produced the following output:

[WARN ][jrockit] MaxPermSize=192m ignored: Not a valid option for JRockit
[WARN ][jrockit] NewRatio=2 ignored: Not a valid option for JRockit
Could not create the Java virtual machine.
Unknown option or illegal argument: -XX:+LogVMOutput.
Please check for incorrect spelling or review documentation of startup options.

Configure your Domain
Both JVM options are invalid for JRockit. So you have to get a hand on your %GF_HOME%/glassfish/domains/domain1/config/domain.xml and comment out or remove the following three lines in the <java-config> section:

<jvm-options>-XX:+LogVMOutput</jvm-options>
<jvm-options>-XX:MaxPermSize=192m</jvm-options>
<jvm-options>-XX:LogFile=${com.sun.aas.instanceRoot}/logs/jvm.log</jvm-options>
After that try restarting your domain and you will see, it works.
If you run the admin console and select "Enterprise Server > JVM Report" you will see, that the Oracle JRockit is now used.
This seems to be a know issue and will be fixed in the next GlassFish 3.1 release.

Why JRockit?
There are a couple of reasons. It's simple the most powerful JVM on earth. But my favorite is the Mission Control Tooling. includes tools to monitor, manage, profile, and eliminate memory leaks in your Java application. You can simply browse any resources on the server and have a very handy tooling for identifying problems. The most powerful thing is the Flight Recording feature. You can monitor your JVM like a blackbox and collect runtime information with minimal overhead. The flight recording option is enabled by default. You simple need to take your probe for as long as you need it and analyze it with the JRMC.
JRockit Flight Recorder does all this by being tightly integrated into the JVM and by being very conscious of its performance overhead. It provides a wealth of information on the inner workings of the JVM as well as on the Java program running in the JVM. You can use this information for profiling and for root cause analysis of problems. It can be enabled at all times, without causing performance overhead—even in heavily loaded, live production environments.
If you are looking for more details also compare my Flight Recorder post. There are some more experimental features available which you could install by simply selecting "Help > Install Plugins". A WebLogic plugin is available. I would love to have a separate for GlassFish also.

Wednesday, January 26, 2011

About @enterprisejava and why it's there .... it's NOT official!

Some questions came up lately about a twitter account of mine. It's called @enterprisejava. This post is to explain the motivation behind it and of course it's there to explain the technologies used to make it happen. If you are expecting any kind of Java here. I have to disappoint you. No Java in this post. Simple plain old web technologies.

UPDATE 08.11.2011
Due to heavy demand, I made this a little more intelligent :) Moving away from the technology described below this is (as of today) a twitter4j based bot which has a very little bad word detection build in and uses the twitter streaming api to simply retweet everything (once ;)) which has any of the following Java EE related keywords:
{"#weblogic", "#javaee", "#websphere", "#tomee", "#javaee6", "#jee6", "#glassfish", "#Coherence", "#JBoss", "#weld", "#CDI", "#hibernate", "#resin", "#JOnAS", "#primefaces", "#myfaces", "#CODI"}
If you do NOT want to be retweeted you need to add the "#ignore" hashtag to your tweet. I am working on a complete revoke list. Stay tuned for updates and more details about this bot!

Twitter and Java EE - the Motivation
A lot is happening out there in twitter land. Many people use it for different things. My main goals are to a) stay in touch with people I would only meet once or twice a year and to b) get the latest headlines from my favorite topics in a very short and condensed way and last but not least c) ask questions and get inspirations. In the spirit of goal b) I used to visit the twitter search and type one of my favorite topics after another and try to collect everything I am interested in. This is easy if you only have one or probably two hashtags to watch. But there are some more if you want to stay up to date with #glassfish, #javaee, #weblogic, #cdi, #jsf or to make it short: the whole Java EE universe.

Twitter and Bots - how to make it simpler?
The simplest way seems to be to write a small bot. Why not? There are many reasons not to do this. At first, you have to implement something and maintain it somewhere. Given the restrictions I have (forced to use public and free infrastructure) I don't want to run into any free account limitations with it. And I don't want to code with a scripting language. And I don't want to reinvent the wheel. Many others had done this before and looking at their code: I hate to write bots...

The technology behind @enterprisejava - how it's done!
But you did it? Right? No ... not really. I gave Yahoo! Pipes and twitterfeed.com a trial. Pipes is a powerful composition tool to aggregate, manipulate, and mashup content from around the web. You basically have some input sources from where to fetch data and some operators and simple functions to manipulate the stream. On a concept level the pipe for @enterprisejava looks like this:
You see four input sources being united into one stream. Each of them represents a twitter atom stream search for a hashtag (compare above). After they are united into one stream, I am looping over each of them to find duplicates (very basic approach). The marked duplicates are filtered out using the unique operator. Next is to filter every single of my bot's own postings. Followed by a swear word detection and some magic to have a generic /via and RT handling. The result is the stream that goes to the pipe output. You can get the pipe output in a couple of formats. Let's stick to RSS (I know, it is dead .. but it works ...) and put it into twitterfeed. You have to tweak the advanced settings to get the sorting right and think about the update frequency and the maximum number of posts at a time ... and link it to your twitter account. Done. That's all.

The icon problem - It is NOT an official Oracle account!
Recently I heard some complaints about the use of the Java (Trademark of Oracle) logo in the icon. I am not a lawyer and I created the logo without having anything bad in mind. First reaction about the complaints was to check the Java Branding Guidelines. As you might have expected: There is a way to use the Java and Java EE logos.
Show your enthusiasm for Java technology
with the Java Get Powered logo. Use it on your
blogs and web sites, t-shirts, coffee mugs,
personal presentations and other belongings.
(Source: 477765_Java_Brand_Guide_1pg_FINAL.pdf)
The bad part is, that anything points to http://java.sun.com/logos/ which is actually a working page on the first look. But if you dig deeper and try to follow the links, that state "Access to the online version of this logo" the links fail. This is not going to become an open letter but I would like to clearly state: Guys: I am part of the good force! I already changed it one time in the last couple of days. And you are still not satisfied with it? Perfect:
Bring back the branding guidelines and let the community contribute to the excitement around Java. I understand the complaints and I am willing to comply with the rules. But I would love to know them before changing the logo again ...

Tuesday, January 25, 2011

JDBC Security Realm and form based Authentication on GlassFish with Primefaces

A very common scenario is to have a protected application. You have users which belong to a group and have different rights in your application. The most basic part is to configure your application server and enable the login for your application. This post guides you through the process of setting up a simple JDBC based realm with GlassFish 3.0.1 and creates a basic login form based on Primefaces.

UPDATE: 28.01.2013
There is a new version of the tutorial out since a few days.

Preparation
I am assuming, that you have NetBeans (7 Beta2, Java), GlassFish (3.0.1 or 3.1 bundled with NetBeans) and MySQL (5.x) installed and you verified that everything single bit is working.

Basic Project Setup
Fire up NetBeans and start a new project. Choose Java Web > Web Application and hit next. Now enter a name (e.g. jdbcrealm) and hit next. Choose a Server or add a new one. Select Java EE 6 as your EE version and hit next. Check the box that states JavaServer Faces and switch to the tab components to select Primefaces as the component suite. Click finish. Now you are set. With your NetBeans project.

Database
Create a new database. There are a couple of ways to do this. I like the MySQL GUI Tooling. Get your copy from the mysql.com website. But you can also use the mysql cmd line. How ever. Execute the following SQL against your installation:

CREATE DATABASE jdbcrealmdb;
USE jdbcrealmdb;
CREATE TABLE `jdbcrealmdb`.`users` (
`username` varchar(255) NOT NULL,
`password` varchar(255) DEFAULT NULL,
PRIMARY KEY (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `jdbcrealmdb`.`groups` (
`username` varchar(255) DEFAULT NULL,
`groupname` varchar(255) DEFAULT NULL)
ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE INDEX groups_users_FK1 ON groups(username ASC);

If we are going to secure our application we need some users with roles. Let's create them, if we are already here:

INSERT INTO users VALUES('admin','adminadmin');
INSERT INTO users VALUES('markus','blogeisele');
INSERT INTO groups VALUES('admin','admin');
INSERT INTO groups VALUES('markus','user');


Domain Configuration
Now switch to the Services tab in NetBeans and right click the Databases node in the tree. Choose new connection and select MySQL (Connector/J driver) in the drop-down. The driver files should show an entry which points to %NB_HOME%/ide/modules/ext/mysql-connector-java-5.1.13-bin.jar. Hit next and enter the connection parameters (Don't forget to select the newly created database: jdbcrealmdb). Remember to test the connection. After that click finish. Back to the projects tab and your application. Right click and select "New > Other > GlassFish > JDBC Connection Pool". Enter a name for the new connection pool (e.g. SecurityConnectionPool) and underneath the checkbox "Extract from Existing Connection:" select your newly created MySQL connection. Click next. review the connection pool properties and click finish. The newly created Server Resources folder now shows your sun-resources.xml file. Follow the steps and create a "New > Other > GlassFish > JDBC Resource" pointing the the created SecurityConnectionPool (e.g. jdbc/securityDatasource).

Next is to copy the %NB_HOME%/ide/modules/ext/mysql-connector-java-5.1.13-bin.jar to your GlassFish domain (%GF_HOME%/glassfish/domains/domain1/lib). Fire up your domain by switch to the services tab in NetBeans and expand the servers node. Right click your GlassFish server node and select start. Open a browser and visit http://localhost:4848/ . Select "Configuration > Security > Realms" and click new. Enter a name (e.g. JDBCRealm) and select the com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm from the drop down. Fill in the following values into the textfields:
JAASjdbcRealm
JNDIjdbc/securityDatasource
User Tableusers
User Name Columnusername
Password Columnpassword
Group Tablegroups
Group Name Columngroupname
Assign Groupsdefault
Digest Algorithmnone
Most of the values are self explanatory. The most important one is the digest algorithm. I have set it to "none" in this case. This means, the passwords are stored in plain text in your DB. You have to use a digest algorithm that fits your required security assurance. You can use whatever algorithm is supported by Java (e.g. MD5, SH-1, SHA-256).
After you are finished, click save.

Secure your application
Done with configuring your environment. Now we have to actually secure the application. First part is to think about the resources to protect. Jump to your Web Pages folder and create two more folders. One named "admin" and another called "users". The idea behind this is, to have two separate folders which could be accessed by users belonging to the appropriate groups. Now we have to create some pages. Let's start with the loginForm.xhtml. Create the file with the following content in the root of your Web Pages folder.

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:p="http://primefaces.prime.com.tr/ui"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Login Form</title>
</h:head>
<h:body>
<p:panel header="Login From">
<form method="POST" action="j_security_check">
Username: <input type="text" name="j_username" />
Password: <input type="password" name="j_password" />
<br />
<input type="submit" value="Login" />
<input type="reset" value="Reset" />
</form>

</p:panel>
</h:body>
</html>

As you can see, whe have the basic Primefaces p:panel component which has a simple html form which points to the predefined action j_security_check. This is, where all the magic is happening. You also have to include two input fields for username and password with the predefined names j_username and j_password. Now we are going to create the loginError.xhtml which is shown, if the user did not enter the right credentials. (use the same DOCTYPE and header as seen in the above example).

<h:body>
<p:panel header="Login Error">
Sorry, you made an Error. Please try again: <a href="#{facesContext.externalContext.requestContextPath}/faces/loginForm.xhtml" >Login</a>
</p:panel>
</h:body>

The only magic here is the href link of the Login anchor. We need to get the correct request context and this could be done by accessing the faces context. If a user without the appropriate rights tries to access a folder he is presented a 403 access denied error page. If you like to customize it, you need to add it and add the following lines to your web.xml:

<error-page>
<error-code>403</error-code>
<location>/faces/403.xhtml</location>
</error-page>

That snipped defines, that all requests that are not authorized should go to the 403 page.

If you have the web.xml open already, let's start securing your application. We need to add a security constraint for any protected resource:

<security-constraint>
<display-name>Admin Pages</display-name>
<web-resource-collection>
<web-resource-name>Protected Admin Area</web-resource-name>
<description/>
<url-pattern>/faces/admin/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
<http-method>HEAD</http-method>
<http-method>PUT</http-method>
<http-method>OPTIONS</http-method>
<http-method>TRACE</http-method>
<http-method>DELETE</http-method>
</web-resource-collection>
<auth-constraint>
<description/>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<display-name>User Pages</display-name>
<web-resource-collection>
<web-resource-name>Protected Users Area</web-resource-name>
<description/>
<url-pattern>/faces/users/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
<http-method>HEAD</http-method>
<http-method>PUT</http-method>
<http-method>OPTIONS</http-method>
<http-method>TRACE</http-method>
<http-method>DELETE</http-method>
</web-resource-collection>
<auth-constraint>
<description/>
<role-name>user</role-name>
</auth-constraint>
</security-constraint>

If the constraints are in place you have to define, how the container should challenge the user.

<realm-name>JDBCRealm</realm-name>
<form-login-config>
<form-login-page>/faces/loginForm.xhtml</form-login-page>
<form-error-page>/faces/loginError.xhtml</form-error-page>
</form-login-config>
</login-config>

The realm name has to be the name that you assigned the security realm before. Close the web.xml and open the sun-web.xml to do a mapping from the application role-names to the actual groups that are in the database. This abstraction feels weird, but it has some reasons. It was introduced to have the option of mapping application roles to different group names in enterprises. I have never seen this used extensively but the feature is there and you have to configure it. Other appservers do make the assumption that if no mapping is present, role names and group names do match. GlassFish doesn't think so. Therefore you have to put the following into the sun-web.xml:

<security-role-mapping>
<role-name>admin</role-name>
<group-name>admin</group-name>
</security-role-mapping>
<security-role-mapping>
<role-name>user</role-name>
<group-name>user</group-name>
</security-role-mapping>


If you now point your browser to localhost:8080/jdbcrealm/ you will see the login screen. Enter your credentials and see what happens.


That's it. By far the longest tutorial I did so far. Hope, you like it. Let me know, if you need more details or have questions. Thanks for reading!

Friday, January 21, 2011

WebLogic 10.3.4.0 + OEPE + Maven + Primefaces 2.2RC

The new WebLogic is there since a few days and we are right in front of another new release of another component: Primefaces 2.2 has RC state at the moment and we are all waiting for a final release happening hopefully the next time. If you are willing to give the existing RC a test drive you can follow this short blog in which I try to shortly summarize the steps necessary to take to get one of my favorite development setups up an running with WebLogic and Primefaces.

What you need
You need the latest WebLogic 10.3.4.0, Maven 3.0 and Primefaces 2.2RC. The first two get installed by the WebLogic installer and you can head over to install the m2eclipse plugin next. You also should install m2eclipse Extras which makes live a lot easier if you are working with web apps and maven. Everything is finished by restarting the OEPE. Now go and grep Apache Maven and install it to a location of your choice.

Creating and configuring your project
Fire up the OEPE. Go to preferences and add your Maven installation to the configured Maven / Installations. Right click "New > Other", select "Maven > Maven Project". Click "Next >". Select the "org.apache.maven.archetypes.maven-archetype-webapp". Click "Next". Enter a valid Group Id, Artifact Id and a package. Click "Finish". You now have a Dynamic Webproject in your Workspace (thanks to m2eclipse Extras). Open the pom and add two repositories:

<repositories>
<repository>
<id>prime-repo</id>
<name>Prime Technology Maven Repository</name>
<url>http://repository.prime.com.tr</url>
<layout>default</layout>
</repository>
<repository>
<id>maven2-repository.dev.java.net</id>
<name>Java.net Repository for Maven</name>
<url>http://download.java.net/maven/2/</url>
<layout>default</layout>
</repository>
</repositories>

After that you have to add the following two dependencies:

<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>2.2.RC2</version>
</dependency>
<dependency>
<groupId>javaee</groupId>
<artifactId>javaee-api</artifactId>
<version>5</version>
<scope>provided</scope>
</dependency>
.
Done with maven. Next is to configure the webapplication. Oben the WEB-INF/web.xml and add the jsf servlet:

<param-value>Development</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>

Now create a WEB-INF/weblogic.xml and add the JSF 2.0 library references to your project.

<library-ref>
<library-name>jsf</library-name>
<specification-version>2.0</specification-version>
<implementation-version>1.0.0.0_2-0-2</implementation-version>
<exact-match>false</exact-match>
</library-ref>


Creating and configuring your WebLogic Domain
Go ahead and configure your local WebLogic Server instance with OEPE. Goto "Server View" and select "New". Select the Oracle WebLogic Server 11gR1 PatchSet 3 server adapter and select or add a Server runtime environment. Click "Next >". Select an existing or create a new Domain Directory. Right click the server entry and "Start" the server. Visit http://localhost:7001/console, select "Deployments > Install". Navigate to WL_HOME/wlserver_10.3/common/deployable-libraries and select the jsf-2.0.war. Click "Next". Accept the "Install this deployment as a library" selection and click "Next". review the settings (nothing to do here for us today) and click "Finish". Now you should see a jsf(2.0,1.0.0.0_2-0-2) deployed on your instance. Fine. Done.

Writing some code
Create an index.xhtml file in your WebContent folder and add some functionality:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:p="http://primefaces.prime.com.tr/ui"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<p:panel header="Hello From">
<p:button outcome="test" value="Next"/>
</p:panel>
</h:body>
</html>

Fine. Don't forget to add another page called test.xhtml with some more content, if you are copying this example :)
Now build and install your application. If you are using the WebLogic 10.3.4.0 Maven Plug-In for Deployment simply type mvn weblogic:deploy to get your primefaces app up and running (or better use m2eclipse ;) and define a new Run as... target).
And that's what the nice stuff is looking like:


What's left?
If you are running without any further changes, you probably see some warnings in your logfiles about missing mime-types like the following.
<Notice> <StdErr> <BEA-000000>: com.sun.faces.context.ExternalContextImpl getMimeType
WARNING: JSF1091: No mime type could be found for file skins/sam/images/ui-default.png. To
resolve this, add a mime-type mapping to the applications web.xml.


In order to avoid this, you have to add the mime type mapping to your web.xml configuration.

<mime-mapping>
<extension>png</extension>
<mime-type>image/png</mime-type>
</mime-mapping>


Thats's all. Now your are running the latest Primefaces 2.2RC on you JSF 2.0 based WebLogic Server. Congratulations!
For those of you, interested: Here is the complete primefaces.zip (4KB) with the configuration. Have fun ...

Monday, January 17, 2011

Using the new WebLogic Classloader Analysis Tool (CAT)

The recently published Oracle WebLogic 11g Patchset 3 contains a new analysis tool called CAT. CAT is a Web-based class analysis tool which simplifies filtering classloader configuration and aids you in analyzing classloading issues, such as detecting conflicts, debugging application classpaths and class conflicts, and proposes solutions to help you resolve them. This post looks into it and shows what is possible and where it is helpful to use.

Getting started
Download and install WebLogic 10.3.4.0 (together with Coherence and OEPE) and use the configuration wizard to create a new domain. Name it whatever you like and make sure you run it in development mode. Deploy your application.

About CAT
Your applications may use many different Java classes, including Enterprise Beans, servlets and JavaServer Pages, utility classes, and third-party packages. WebLogic Server deploys applications in separate classloaders to maintain independence and to facilitate dynamic redeployment and undeployment. Because of this, you need to package your application classes in such a way that each module has access to the classes it depends on. In some cases, you may have to include a set of classes in more than one application or module. All this makes applications larger as they include multiple frameworks for their functionality. And there are many sources (open source, commercial sources, or developed in-house) to handle. Using the capabilities of WebLogic server applications can use those dependencies in different ways:
- Framework JARs bundled directly in the modules
- MANIFEST classpath references to other JARs
- Server application and JAR libraries
- Server system classpath
As the application classpath grows, it gets cumbersome for application developers to understand which class is getting loaded from which source. Sometimes applications bundle different versions of JARs than those in the system classpath.

CAT is a stand-alone Web application, distributed as a single WAR file (WL_HOME/server/lib/wls-cat.war). It is deployed as an internal on-demand application only in development mode and the deployment happens upon first access. If the server is running in production mode, it is not deployed automatically but you can deploy it manually, just like any other Web application. According to the documentation you can deploy it to any WebLogic Server version 10.3.x and above. It helps developers understand, analyze, and resolve classloading issues in their applications. CAT will report potential problems and also present solutions for resolving those issues.

Using CAT
Point your browser to http://wls-host:port/wls-cat/ and enter your credentials. After the automatic deployment finished, CAT displays all your currently running applications and modules. CAT lets you:
- Analyze classloading conflicts
- View the system and application classloaders
- Generate reports
CAT analyzes classes loaded by the system classpath classloader and the WebLogic Server main application classloaders. You can perform analysis at the class, package, or JAR level.

Display basic and detailed information about applications and modules
Select a module or application on the left hand and you will see general information in basic view. This includes a very basic summary, first warning overview and a list of referenced libraries.If you select the detailed view the warnings change. At the first sight there is no obvious difference between the basic and detailed view except the fact that you also have some more details about the System Classloaders. But this information is not present from time to time. There seems to be room for improvement here :)

Analyze classloading conflicts
If you deploy the console application and inspect it, you have your first example with some potential conflicts. Select Application: consoleapp Module: console on the left hand menu and select detailed view. Now you have a brief warning "There are potential classes in conflict". Now select "Analyze Conflicts" and look at what's happening. The CAT displays the potential number of conflicts. In case of the console app there are potentially 533 classes in conflict state. Struts seems to be the troublemaker here. A suggested solution tells you to use the reversed web app classloader by setting the prefer-application-packages in your weblogic.xml.
If you click on a single potentially conflicted class, you see some more information. Beside the complete list of classes in conflict (in this case APP/INF lib and WEB-INF/lib org.apache.struts.Globals.

Get suggestions for configuring filtering classloaders
The filtering classloader acts as a barrier between the application classloaders and the system classloaders. By configuring the filtering classloader correctly, the application can choose to load certain classes locally rather than from the system classpath. You even get hints on actual settings with a filtering classloader in place.

Display the classloader hierarchy and the entire classpath for each classloader
If you click on "Classloader Tree" and chose the "detailed" view you get a complete list of classloaders, their loaded jars and filters. Covering all available classloaders. If you click on the HashCode link you get a details analysis about exactly this classloader in which you could also search for a class or a resource. It is possible to analyze both classes as well as resources such as XML or property files. To analyze a class, for example, the class Globals in package org.apache.struts, type in the fully qualifed class name, for example, "org.apache.struts.Globals". If you are searching for a resource, prefix your search with "#".
You can also see the classloader search order. But it's hard to compare the hashes and remember them.

Generate Reports
If you click the link "Generate Report" the complete classloader tree is exported to an XML file (cat-report-consoleapp.xml) which makes it more easy to search within. Beside the single classpath entries it also exports the conflict elements.

Final thoughts
Hey. It's nice! Thanks Oracle. This will make my life a little easier while searching for conflicts. But: It's a very very basic development tool. Usability is far off from good and this includes navigation, look and feel and behavior. The basic/details concept does not look very thought over. I bet, there are other versions of the tool around which have far more capabilities or there were others planed. I don't know how big the suggested solution space is. At first, it seems to be limited. I'll give it a more practical test in the near future and I am very excited to see, how this is working with real complex projects.

Saturday, January 15, 2011

Installing and Using the WebLogic 10.3.4.0 Maven Plug-In for Deployment

It happened very silent. The Oracle Middleware 11g Patchset 3 is available since yesterday. To me all the fancy new Oracle stuff (ADF, SOA and more) is not too important at the moment. But one thing is: The backbone of it. My all time favorite WebLogic Server. It's now at version number 10.3.4.0 and comes with some minor tweaks in general this time. One of the things I was waiting for since some time is the new WebLogic Maven plugin. Now you can use an Apache Maven plug-in for WebLogic Server (weblogic-maven-plugin) to perform deployment operations similar to those supported by the command-line utility, weblogic.Deployer. The plug-in lets you deploy, redeploy, update, and such, applications built using Maven to WebLogic Server from within the Maven environment.

Getting started
Get your copy of the latest WebLogic (together with Coherence and OEPE) and install it. Download and configure Apache Maven 2.x.
Next is to configure the new plugins. Everything gets a lot simpler if you start with a blank domain. Start the configuration wizard and create one. Execute the user_projects\domains\base_domain\bin\setDomainEnv.cmd/.sh to prepare your environment. Now we can go on and configure the plugin jar file. This could be done with the WebLogic JarBuilder Tool (wljarbuilder) which ist located at MW_HOME/wlserver_10.3/server/lib/ change to that folder and execute: java -jar wljarbuilder.jar -profile weblogic-maven-plugin. This will generate your barely 59 MB big weblogic-maven-plugin.jar. Don't think about the weird output ;)
Open the jar file with your favorite ZIP tool and extract the META-INF\maven\com.oracle.weblogic\weblogic-maven-plugin\pom.xml to MW_HOME/wlserver_10.3/server/lib. If you look at the file you get the maven dependency information:

<groupId>com.oracle.weblogic</groupId>
<artifactId>weblogic-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>
<version>10.3.4</version>

These fields identify the plug-in and mark a specific place in a Maven repository, acting like a coordinate system for Maven projects.
Now you have to install the plugin to your local maven repository. Execute:

mvn install:install-file -Dfile=weblogic-maven-plugin.jar -DpomFile=pom.xml

If you have never ever used Maven before, you should probably go and read other pages before but if you came here and you are wondering about what's happening after you executed this command for the first time ever: Maven is downloading the internet to your local repository and finally installs the generated jar file there, too.

Using the WebLogic Maven Plugin
You can use the plugin in two modes. First is from the cmd line. You can use the following goals: deploy, list-apps, redeploy,start-app,stop-app,undeploy,update-app.
If you followed my explanation you can simply type the following:
mvn com.oracle.weblogic:weblogic-maven-plugin:help
Or you can include the plugin in your own applications's pom.xml file:

...
<build>
<plugins>
<plugin>
<groupid>com.oracle.weblogic</groupId>
<artifactid>weblogic-maven-plugin</artifactId>
<version>10.3.4</version>
<configuration>
<adminurl>t3://localhost:7001</adminurl>
<user>system</user>
<password>weblogic1</password>
<upload>true</upload>
<action>deploy</action>
<remote>false</remote>
<verbose>true</verbose>
<source>${project.build.directory}/${project.build.finalName}.${project.packaging}</source>
<name>${project.build.finalName}</name>
</configuration>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
</build>
...


You can add the plug-in into any life cycle phase of the project. Optionally, you can add a goal to any of the default Maven life cycle phases by adding an executions tag in the pom.xml file. The goal is then bound to that particular phase of the Maven life cycle. As shown above the goal is bound to the "install" phase of the life cycle. By doing this, every time you run the mvn install command, the deployment plug-in is also called.

Wondering about the long command?
The cmd line command is quite long. You can and should shorten the invocation name of the plugin. A couple of steps have to be taken to achieve this.
You have to change the pom.xml file and add:

<build>
<plugins>
<plugin>
<artifactid>maven-plugin-plugin</artifactId>
<version>2.3</version>
<configuration>
<goalprefix>weblogic</goalPrefix>
</configuration>
</plugin>
</plugins>
</build>

After that modify the settings.xml file located in your $HOME/.m2 directory with the following lines:

<plugingroups>
<plugingroup>com.oracle.weblogic</pluginGroup>
</pluginGroups>

before you provision the plug-in in your Maven repository.

After all this is done, you can call all commands with a shortened version:
mvn weblogic:deploy

Conclusion
Even if the documentation states, that the plugin should use Maven 2.x I tried everything with Maven 3 and did not discover any problems in general.
I will give it a test drive production near and will report further findings. At the moment everything looks very promising and simple. Thanks guys for providing this one!

Friday, January 14, 2011

QR-Codes with GlassFish and PrimeFaces

I've been playing around with QR-Codes lately. To make it short. I love them. If you have a nice, little reader on your mobile you have a very handy way of getting contacts, urls, email adresses, and short texts into your mobile. If you look around, you can find a lot of websites offering to create such stuff for you.
One of the most prominent are the Google Chart Tools. If you like to, you can simply use this online version. An image tag with the following url
https://chart.googleapis.com/chart?
chs=150x150&cht=qr&
chl=Hello%20world&choe=UTF-8
gives you a very simple "Hello World" QR-Code. But what happens if you are not able or willing to access any free service on the net? What happens if you need to create your own QR Codes? Here we go. That was part of the question I was asking myself. And here is a short howto.

Getting started
Make yourself comfortable with whatever programming language you want to use. But for this tutorial you are going to need a Java EE Webcontainer or at best one of the latest GlassFish 3.x. Next is to grep your copy of Primefaces and one of your favorite development environments. If you are naughty you could also use the latest NetBeans 7.0 Beta which provides all prerequisites out of the box.
Start by creating a new web-project and make sure to check the box beside "Enable Context and Dependency Injection" and also make sure you use the JSF 2.0 implementation with PrimeFaces as the component library. If this is done, you have to make a decision for the QR-Code library to use. I did a simple search on google and was somehow disappointed. Many many options but mostly readers or even closed source. One very promising result was ZXING. ZXing (pronounced "zebra crossing") is an open-source (Apache v2), multi-format 1D/2D barcode image processing library implemented in Java. If you look at the samples you mostly find decoding samples. But there also is an Encoder.
That's what I was looking for. Get the 1.6 release which has roughly 60 MB and start by unpacking it. Next is to build the core project (mvn install). Which gives you a handy (325KB) core-1.6-SNAPSHOT.jar to copy as a library to your netbeans project. Now your all set and we can start coding.

Encoding Strings
Wow. That is not too easy. Even if there is an Encoder, you still have to do some work to get this done. If you look around the google groups discussions forum you quickly find some solutions. One came up with a complete generateQRCodeImage() Method which you can simply copy and use for your own trials.
The basic magic is to not only have the simple QR-Code written but also have the "the quiet zone" as described in QR code spec (at least 4 modules on each size). So here is all you have to do:

QRCode qrcode = new QRCode();
Encoder.encode(code, ErrorCorrectionLevel.L, qrcode);

Plus all the magic you need for having "the quiet zone" in place (please refer to the mentioned method above for a complete walthrough). After that you simply have to write out to whatever stream you need.

ImageIO.write(image, "png", out);


Putting it into a Servlet
The simplest approach is to encapsulate everything into a servlet. All you need is an OutputStream to which to write your QR-Code:

generateQRCodeImage(out, code, width, width);

If you add some magic parameters you can even have you own @WebServlet(name = "QRCodeGenerator").

Primefaces are better
But who wants to use Servlets our days? JSF 2.0 and Primefaces are the ones to use. All you need is the Dynamic Image Streaming component from Primefaces. Use the example and put your generateQRCodeImage method into that managed bean.

@Named(value = "qrcontroller")
public class QrImageController

Small difference, you now have to use the StreamedContent API for getting the image data. You have to play around a bit to find a solutions. The fastest way was to simply get an ByteArrayInputStream and convert it to a DefaultStreamedContent. That worked. Even if you have some additional steps for converting the BufferedImage. Finally all you have to do is to put the component to your facelet

<p:graphicimage value="#{qrcontroller.qrcode}"></p:graphicimage>

Right click your project, select run and you are done!
Fine! Thanks for reading! If you have comments or other libraries you can recommend: I would be happy to read about what you are thinking.

Wednesday, January 12, 2011

Java EE 7 - what's coming up for 2012? First hints.

Even if the actual Java EE 6 version is still not too widespread, we already have seen the first signs of the next EE 7 version written to the sky. Roberto Chinnici did a first presentation about the general future at JavaONE, September last year. At Devoxx we saw a talk about The Future Roadmap of Java EE done by Jérôme Dochez, Linda DeMichiel and Paul Sandoz. And finally there is a GlassFish Podcast Episode #071 - Java EE 7 discussion with Roberto Chinnici. The latest addition could be the "Future of Java EE" keynote by Jerome Dochez seen at JavaONE Brazil.

The theme - cloud
The theme for Java EE 7 is the cloud. Clouds tend to be elastic, and most of the current computing centers are not. In terms of Java EE 7 we're talking about multi-tenancy, application versioning, support for NRDBMS stores but also about modularity, trying to leverage what will be done at the JavaSE level. The basis is a virtualization layer. Followed by state management for scalability and a number of services on top. What is called a "Java service" in the stack should be the equivalent to the existing containers. That's what runs your Java code. But there will be more services that will be formalized to provide a comprehensive platform.
As already expected during Devoxx, JAX-RS and JPA seemed to be the closest to being filed as JSRs.

First JSRs
And that's what happened yesterday (11/01/11). JSR 339: JAX-RS 2.0: The Java API for RESTful Web Services and JSR 338: Java Persistence 2.1. Even if we are still missing the umbrella JSR for Java EE 7, taking a closer look at the two gives some brief hints on when to expect it.

JAX-RS 2.0
The JAX-RS 2.0 draft JSR has been around since the end of November 2010. And even Paul Sandoz's slide deck from Devoxx session about "JAX-RS, Java EE6 and the Future" (PDF) points out some of the enhancements coming.
The proposed draft goes into more details. The key points are: Two client APIs, Hypermedia support, JAX-RS compatible MVC architecture (with JSPs as one kind of views), Parameter validation, Integration with JSR 330 (DI), a simple asynchronous request processing model, server side content negotiation and some minor tweaks like bug fixes.
The Reference Implementation will be developed as part of Project Jersey.

JPA 2.1
It was speculated, that JPA has a long list of potential enhancements, ranging from dynamic definition of PU, more control on persistence context synchronization, mapping between JPQL and criteria queries and much more. And here we go: Additional support for the use of custom types and transformation methods, "fetch groups" and/or "fetch plans", immutable attributes and readonly entities, user-configurable mapping naming strategies, more flexibility in the use of generated values, additional mapping metadata, support for multitenancy, additional event listeners and callbacks, dynamic definition of persistence unit, JPQL support for stored procedures, and some more.
The Java Persistence RI is being developed under the open source EclipseLink project and is being made available through GlassFish.

As usual, both already filled JSRs are proposals. The EGs will have to negotiate on them. And even if they will be included as a required part of the Java Platform, Enterprise Edition version 7 aligning the timeline of both JSRs with that of Java EE 7 may therefore impact the scope. So the next step is to wait for the JSR Review Ballot which will end on 24 Jan, 2011 for both.

What's the timeline?
Both mention Q3/Q4 2012 as schedule for the final release. Early drafts will be available at the end of 2011. All this could point to the end of 2012 as the release date for Java EE 7.

To be honest, both JSRs are not the hottest ones for EE 7. At last to me. There is a lot of stuff to come. I am personally looking forward to see the revised module and take a deeper look at the integration with the new Java SE 7, 8, 9 features.

Friday, January 7, 2011

GlassFish 3 vs. JBoss 6 - Is the Web Profile ready for the Enterprise?

Wow. We still are in the holiday season and the emotions rise with the announcement of the latest JBoss AS 6 release. My valued friend Arun Gupta did a post about "Which Java EE 6 App Server ? - JBoss 6.0 or GlassFish 3.x" a few days ago an today Anil responded with JBoss AS6 vs Glassfish 3.x. It's obvious that even both names GlassFish and JBoss are mentioned in the topics and the discussion seems to be about having clustering support or a well documented users guide, I believe, that all this is basically about the value of the Java EE 6 Web Profile for Enterprise Applications.

What's the Web Profile?
If you refer to my post from last year, its thought of as a minimal specification, so a vendor is free to add additional services in their concrete implementation. A more complete comparison about what's contained in it could be found on glassfish.org.
Some of the most basic parts of Java EE are missing in it. Some very important parts are:
- JAX-WS 2.2
- JMS 1.1
- JavaMail 1.4
- Full EJB 3.1 API
Even if @AdamBien states, that "webprofile + JAX-RS + JMS -> should be sufficient for 90% of all projects." I personally believe, that there is more missing. One very simple example are the TimerBeans, that simply are not contained in the EJB 3.1 lite version. Same is true for JavaMail. Tell me about any application not sending some kind of mail to it's users.

What does Enterprise Software development mean?
Beside the technical parts, there obviously is more to enterprise grade software development. Essential parts are:
Having ...
- a stable Vendor
- a strong history and many references
- a suitable documentation for the products
- the option to buy any kind of support with according SLAs
- the option to integrate the products into the existing environments.
And many others. I know about comparison sheets containing more than 500 points for one individual enterprise.....

So, now: What's the right decision: JBoss or GlassFish?
Having all this in mind and trying to compare both distributions, it simply is clear, that the JBoss AS 6 release is a Web Profile only version. GlassFish 3.x is a Java EE 6 full stack implementation. Beside this there are obvious differences in the other parts, I consider important for enterprise grade usage. Everybody is free to make it's own comparison on the relevant parts for both servers. Without being able to make this too detailed for public reference I can state, that for now and the actual available releases of both servers GlassFish is the leader in terms of being suitable for an enterprise grade production environment relying on Java EE 6. And this is explicitly not a comment on technical quality or even the vendor. It's simply my own opinion about Web Profile vs. Full Stack and their use within the enterprise.

For me, this would be a great point to focus again. JBoss guys on quickly developing and delivering their full stack version and Oracle to proof that they are willing to stabilize the Java EE and GlassFish community and push their product forward.

Thursday, January 6, 2011

Review: "Beautiful Code - Leading Programmers Explain How They Think" edited by: Andy Oram, Greg Wilson

Being part of the O'Reilly Blogger Review Program since last year, it was time to request a first book for review. After the latest more Java and GlassFish centric reviews on this blog it is time for more theory.
Beautiful Code is a collection of essays from some well known software engineers. I was really looking forward reviewing this one because of the interest I have in other people's ways of solving problems. To make it short: It's an amazing book. And it is very hard to read. If you are thinking about buying it, make sure you have the time to deep dive into it, otherwise it will only be a nice, blue spine in your rack.

Book: Beautiful Code - Leading Programmers Explain How They Think
Language : English
Paperback : 624 pages [9.1 x 7.1 x 1.2 inches ]
Release Date : June 2007
Publisher: O'Reilly Media; 1 edition (June 26, 2007)
ISBN-10: 0596510047
ISBN-13: 978-0596510046
Edited By: Andy Oram, Greg Wilson

The Editors
The book was put together by Andy Oram and Greg Wilson. Both names, I have not heard before. Let's get a hand on their biography (Taken from an Safari Books Online Interview with both). Andy Oram is an editor at O'Reilly Media specializing in free software and open source technologies. His work for O'Reilly includes the first books ever published commercially in the United States on Linux, and the 2001 title Peer-to-Peer. Andy is also a member of Computer Professionals for Social Responsibility and writes often for the O'Reilly Network and other publications on policy issues related to the Internet and trends affecting technical innovation and its effects on society.
Greg Wilson holds a Ph.D. in Computer Science from the University of Edinburgh, and has worked on high-performance scientific computing, data visualization, and computer security. He is the author of Data Crunching (Pragmatic Press, 2005) and Practical Parallel Programming (MIT Press, 1995), and is a contributing editor at Doctor Dobb's Journal, and an assistant professor in Computer Science at the University of Toronto.


The Content
It's a quick and easy beginning. After 25 pages of preface, contents and some reading information you get started by chapter 1 which is written by Brian Kernighan and is about "A Regular Expression Matcher". The chapter itself has 10 pages and describes in detail the algorithms and approaches to implement the topic. It happens, that you hit the first sorcecode on page 27. No big surprise. If you are through this, you have a brief impression what to expect in the following 32 chapters. Each of them is organized independently and you have to spend a couple of hours with each to fully understand it. An excerpt of what is waiting for you:

Chapter 2, Subversion's Delta Editor: Interface as Ontology, by Karl Fogel
Chapter 3, The Most Beautiful Code I Never Wrote, by Jon Bentley
Chapter 8, On-the-Fly Code Generation for Image Processing, by Charles Petzold
Chapter 10, The Quest for an Accelerated Population Count, by Henry S. Warren, Jr.
Chapter 16, The Linux Kernel Driver Model: The Benefits of Working Together, by Greg Kroah-Hartman
Chapter 18, Python's Dictionary Implementation: Being All Things to All People, by Andrew Kuchling
Chapter 23, Distributed Programming with MapReduce, by Jeff Dean and Sanjay Ghemawat
Chapter 28, Beautiful Debugging, by Andreas Zeller

And there are many more chapters in it.

Writing and Style
It has been a hard time for me as a non native speaker following the different authors. Each has a slightly different style and even if the editors did a great work with them it gets very theoretical and you have kind of academic writing to work through to understand everything completely. The fact, that every chapter has a different structure also makes this a hard read.
Nearly every chapter uses a different programming language. You come across Haskell, Java, C++, pseudocode, Python and some more. Even if an experienced programmer should be able to understand any dialect, you have to find your reading speed through the book. This is hard sometimes. Another point which slowed down my reading speed are the equitations. If you like them. Perfect. There are more of them in there. And if you are willing to experience the beauty behind the solutions, you have to understand them.

My expectations
To be honest. I did not had too much. I was looking for some very decent solutions of other programmers. I was willing to look at their way of solving problems and I was hoping to be surprised with a couple of unusual experiences. That worked for me. You can find examples of some very interesting problem domains with working solutions. The people delivering the content for the book play in a league of their own and after reading a couple of chapters I fully understand one of the answers from the editors in the safari books online interview:
Safari: What was the most challenging part of putting together Beautiful Code?
Wilson: Believe it or not, it was persuading people that they actually had something to contribute. Many of the authors' first reaction when we approached them was, "That sounds great, but I don't think I've ever written any code I'd call 'beautiful'."

Conclusion and recommendation
If you are looking for beautiful code: Buy this book. But be prepared. It's not an easy read and don't expect to simply read through it. The best part is: You don't have to. It's chapters are readable one by one and you don't miss a bit, if you start with 33 or simply focus on the parts you like the most.

Monday, January 3, 2011

Five ways to know how your data looked in the past. Entity Auditing.

A transactional application often requires to audit the persistent entities. The reasons for this are different. Sometimes you simply have to be able to track down changes and build up a history of changes. Other frequent requirements are related to long term rollback features or even archiving in accordance with legal audit requirements. There are different approaches to auditing in general. Here is an excerpt of what I know, you could come up with more I am sure.
  • Change log
    You only need to know, who changed which entity type.
  • Simple change tracking
    You are only interested to know if something changed. Can audit a complete entity or any subset of information from it.
  • Complete history
    You need a complete auditing about who changed what and when. Need to keep all old entity versions.
  • Complex change tracking
    Need to know who changed which value to which new value and when. Even combined with additional requirements.

All of the above could be addressed with the below approaches. They generally differ by implementation complexity and performance. The more complex you auditing needs are the more impact you can expect on performance in general. You should also keep in mind, that depending on audit level and change frequency your data volume will grow very fast.
To implement it, there are a couple of technical options. Here are the five ways I would come up with, if you would ask me.

EJB Interceptors
You could use EJB Interceptors. All you need is a facade around your entity operations. Create an AditInterceptor and add it to your EJB methods. Adam Bien has a nice and simple example on his blog.

Pro: Simple programatical approach.
Con: This is not a very entity centric approach. You have to find the right repository facades and methods for auditing. If this is a usable approach depends on the amount of auditing needed.

CDI Interceptors
If you don't have EJBs in your application you could also use plain CDI interceptors. Refer to this older post of mine to see a simple example.

Pros/Cons: Same as EJB Interceptors.

JPA Event listeners
If you have plain JPA you could make your application audit changes via the life cycle callback methods. The JPA specification describes how an entity or a separate, stateless entity listener instance can receive callbacks during various life cycle state transition of an entity. Seven transitions are defined: @PrePersist, @PostPersist, @PreRemove, @PostRemove, @PreUpdate, @PostUpdate and @PostLoad. To receive these callbacks either annotate certain methods of the entity class itself or of a separate entity listener class. In addition to this, most of the JPA implementations also have some kind of listeners available, which could be used for this.

Pro: Simple programatical approach. Extended features available from the JPA implementations.
Con: You have to get hand on "old" entities. This is not too simple in general. And you have to understand the lifecycle methods needed here.

Hibernate Envers
Envers is library for Hibernate that help to easily achieve audit functionality. It has been created by Adam Warski and is part of Hibernate core since 3.5. Basically you annotate an Entity with @Audited to tell Envers that this class needs to be audited. All fields except those annotated with @NotAudited will be audited. You configure the org.hibernate.envers.event.AuditEventListener with any of the following types: post-insert, post-update, post-delete, pre-collection-update, pre-collection-remove, post-collection-recreate. The org.hibernate.envers.auditTablePrefix and org.hibernate.envers.auditTableSuffix properties are helping to add a prefix or suffix your audit tables. The audit tables contain a REV column, which specifies the object access type. 0 means creation, 1 means modification and 2 means deletion. You could even get an object with a previous version using the AuditReader.find() method.

Pro: Very easy to implement. Rich API to use.
Con: You more or less archive the complete entity. There is now way ootb to audit which attributes really changed. This is an very generic all or nothing approach.

Database triggers
You can for example use some generic "before update" triggers to compare new and old values and log the changes. (See this Ask Tom answer on how to do this.)

Pro: If you know how, it's very easy and right at the heart.
Con: You have a very high database dependency, so it's in general no good idea if you have to have a portable solution at hand.

Bottom line
Whatever requirements you have. I can promise you, that it will never be a simple solution. In general it's best to evaluate your purpose for auditing in detail. In order to have an appropriate auditing strategy and to avoid unnecessary auditing, you must have a clear understanding of the reasons for auditing. In order to prevent unnecessary audit information from cluttering the meaningful information, it is important to audit the minimum number of statements, users, or objects required to get the targeted information.

2010 - The year in review. Some statistics.

Seems as if we all finally made it. 2011 is here and we hopefully managed the transition without any bigger problems. This usally is the time for some statistics and reviews. Let's start with the facts of this blog.It had rougly 90k visitors in 2010 with around 115k pageviews. That is awesome! Thank you for all your visits!
The top five topics which had about 23k pageviews:
1) Java EE 5 or 6 - which to choose today
2) Java SE 7, 8, 9 - The Road Ahead
3) JDK 1.6.0_21-b06 Eclipse vs. 1.6.0_21-b07 Oracle
4) Java SE 6 release 21, the Java Hotspot VM 17.0 and G1
5) GlassFish vs. WebLogic - 10 visions for the future

As expected, the hottest time in the year was during JavaONE and Open World. People came here mostly send from google, dzone and java.net or visited this blog directly. I have had a small number of 114 posts last year.

Personaly I flew a total distance of roughly 1,23 earth circulations. With the shortest flight being 300km and the longest 9.500km. This was a total of 81,8 hours inflight entertainment on ten different plane types for me. In total I produced 6,705 kg CO2 in 2010. Thats more than douple of this, I did in 2009 :( Sorry for that ....

I posted 626 pictures to flickr. Most of them taken during the three big conferences I visited in 2010 (Kaleidoscope, OpenWorld/JavaONE, DOAG Conference).

I tweet a little. On average 14,6 tweets per day with roughly 50% of them being retweets of others. My top five words: rt, java, oracle, new, glassfish. My top five hashtags: #java, #glassfish, #javaone, #oracle, #aced.

All in all this was an exciting year. I loved to be part of a vital blogger scene around Java, Oracle, GlassFish and WebLogic. And I hope that I will be able to continue in 2011. Thanks again for visiting!