April 30, 2012

How to set JAVA_HOME environment variable in Ubuntu

Setting the JAVA_HOME variable can be done in several ways.

1. Globally and at System level, i.e. no user is required to be logged in. This is the preferred way if you are configuring a server and planning to use boot strapped program that needs JAVA_HOME variable.
$ vi /etc/environment
...
JAVA_HOME=/usr/lib/jvm/java-7-oracle
...
2. Globally and set for all logged in user, i.e. one user is needed to be logged in, to have the JAVA_HOME variable set.
$ vi /etc/bash.bashrc
...
JAVA_HOME=/usr/lib/jvm/java-7-oracle
...
3. User specific. Then the variable is only set when the designated user is logged in.
$ vi /home/$USER/bash.bashrc
...
JAVA_HOME=/usr/lib/jvm/java-7-oracle
...


If you have different installed JDK you might find this blog useful on how to manage different JDK on Ubunut http://magnus-k-karlsson.blogspot.se/2012/03/managing-multiple-java-installation-on.html.

April 25, 2012

JBoss EJB 3.0 Security with Annotation and Declarative with Deployment Descriptor (ejb-jar.xml and jboss.xml)

The Security configuration and programming model has been much simplified with Java EE 5 and especially with the general introduction of Annotation. The Annotation has reduced significantly the XML cacophony. But in some cases declaring thing external from the source code is good, and an example of that is Security.

So lets start with an easy EJB and use standard Java Enterprise Bean Security Annotations [1], but we will also use JBoss specific JAAS Security Annotation. Later on we will test that we can override these values by declaring security on the EJB deployment descriptor ejb-jar.xml (Java EE) and jboss.xml (JBoss Container Specific)

@javax.ejb.Local
public interface FooLocal {

    public void method1();

    public void method2();
}
@javax.ejb.Remote
public interface FooRemote {

    public void method1();

    public void method2();
}
@javax.ejb.Stateless
@org.jboss.ejb3.annotation.SecurityDomain("mydomain")
@javax.annotation.security.DeclareRoles({ "USERGROUP", "ADMINGROUP" })
public class FooBean implements FooLocal, FooRemote {

    @javax.annotation.security.RolesAllowed({ "USERGROUP" })
    public void method1() {
        print();
    }

    @javax.annotation.security.RolesAllowed({ "ADMINGROUP" })
    public void method2() {
        print();
    }

    public void print() throws PolicyContextException {
        final String key = "javax.security.auth.Subject.container";
        Subject caller = (Subject) PolicyContext.getContext(key);
        Set<principal> principals = caller.getPrincipals();
        for (Principal principal : principals) {
            LOGGER.info("class=" + principal.getClass() + ", principal="
                    + principal + ", name='" + principal.getName() + "'");
        }
    }
}
NOTE: Do not use JNDI prefix java:/jaas in the SecurityDomain annotation.

NOTE: SecurityDomain has since JBoss 5.X changed package name, if you are using JBoss 4.X it is org.jboss.security.annotation.SecurityDomain.

In our first example the deployment descriptors can be quite empty.

META-INF/ejb-jar.xml:
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
    version="3.0">

</ejb-jar>
META-INF/jboss.xml
<?xml version="1.0" encoding="UTF-8"?>
<jboss xmlns="http://www.jboss.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss_5_0.xsd"
    version="5.0">

    <security-domain>java:/jaas/mydomain</security-domain>
</jboss>
NOTE: Since JBoss 5.X the JNDI prefix java:/jaas is now optional, but left for backward compatibility.

And finally we will have to define our security domain in $JBOSS_HOME/server/$CONF/conf/login-config.xml.
<application-policy name="mydomain">
    <authentication>
        <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required">
            <module-option name="usersProperties">props/mydomain-users.properties</module-option>
            <module-option name="rolesProperties">props/mydomain-roles.properties</module-option>
        </login-module>
    </authentication>
</application-policy>
Now lets get started with overriding these security settings with the deployment descriptors. The two deployment descriptors are quite open and writing of them can be done in different ways. But I use these guidelines, for hopefully making things a little more simpler.

Try to use the generic ejb-jar.xml as much as possible. And only put specific container configuration in the jboss.xml.

And changing security is a Java EE feature so declaring security is done in the ejb-jar.xml file.

META-INF/ejb-jar.xml
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
    version="3.0">
     
    <assembly-descriptor>
        <security-role>
            <role-name>USERGROUP</role-name>
        </security-role>
        <security-role>
            <role-name>ADMINGROUP</role-name>
        </security-role>
        <method-permission>
            <role-name>ADMINGROUP</role-name>
            <method>
                <ejb-name>FooBean</ejb-name>
                <method-name>method1</method-name>
            </method>
        </method-permission>
        <method-permission>
            <role-name>ADMINGROUP</role-name>
            <method>
                <ejb-name>FooBean</ejb-name>
                <method-name>method2</method-name>
            </method>
        </method-permission>
    </assembly-descriptor>
</ejb-jar>


Reference:
[1] Java EE 5 Tutorial: http://docs.oracle.com/javaee/5/tutorial/doc/bnbyl.html
[2] JBoss Security FAQ: https://community.jboss.org/wiki/SecurityFAQ

Managing Java Enterprise Dependency (javaee-api) with Maven by Using JBoss Dependency (org.jboss.javaee)

In my previous blog (http://magnus-k-karlsson.blogspot.se/2012/04/handling-java-enterprise-dependency.html) I was talking about the hardship of using Maven when developing Java Enterprise Applications. And this following up blog I will show the best practice I think of handling JBoss Enterprise dependency with Maven.

First when using JBoss dependency you will have to add the JBoss Repository. You can add this in your personal Maven configuration file, settings.xml as described at the JBoss Community page https://community.jboss.org/wiki/MavenGettingStarted-Users. Or you can add the repository in your parent pom. I think the best way is to do it in your parent pom, since it is more clear to less experience programmers.

<repositories>
    <repository>
        <id>jboss-public-repository-group</id>
        <name>JBoss Public Maven Repository Group</name>
        <url>https://repository.jboss.org/nexus/content/groups/public-jboss/</url>
    </repository>
</repositories>
<pluginrepositories>
    <pluginrepository>
        <id>jboss-public-repository-group</id>
        <name>JBoss Public Maven Repository Group</name>
        <url>https://repository.jboss.org/nexus/content/groups/public-jboss/</url>
    </pluginRepository>
</pluginRepositories>
I have left out the rest of the configuration, since it is anyway default values, you can read more about the above configuration below:

Maven 2.2.1
http://maven.apache.org/ref/2.2.1/maven-settings/settings.html

Or if you already have upgraded to the latest Maven 3 version:
http://maven.apache.org/ref/3.0.4/maven-settings/settings.html

If you are using a different version of maven simple change the above URL with you maven version.

Now to the real work adding JBoss Enterprise Dependency. The hardest part is the first part. What is the groupId and artifactIf for the JBoss dependency? And this is not at all clear at the beginning. But Red Hat have submitted a version fil with JBoss:

JBoss AS (Community Edition) and JBoss EAP (Enterpise Application Platform)
$JBOSS_HOME/jar-versions.xml

When looking for Maven Dependency groupId and artifactId you should look for implVendorID which is groupId and implVersion which is the version in Maven. But the problem is in most cases implVendorID is replaced with an URL, that will not help us much.

But JBoss have actually deployed there dependency matrix in there repository:
https://repository.jboss.org/nexus/content/groups/public-jboss/org/jboss/jbossas/jboss-as-component-matrix/

As you can see they have preserved the groupId and artifactId for most of there JBoss releases and that is a good, because that makes component more easy to discover. But instead of now searching the component matrix for the specific dependency and it version you can actually import this pom to maven with

<?xml version="1.0" encoding="UTF-8" ?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
...
    
    <properties>
        <jbossas.version>5.1.0.GA</jbossas.version>
    </properties>

    <dependencymanagement>
        <dependencies>
            <dependency>
                <groupid>org.jboss.jbossas</groupId>
                <artifactid>jboss-as-component-matrix</artifactId>
                <version>${jbossas.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>    
</project>
And now to import the JBoss Enterprise Dependency:
<dependency>
    <groupid>org.jboss.javaee</groupid>
    <artifactid>jboss-javaee</artifactid>
    <scope>provided</scope>
</dependency>
NOTE: that here I'm not specifying the version number that is retrieved from the above pom import. You can verify that either with m2eclipse or with Maven:
$ mvn dependency:tree

Sadly the JBoss Enterprise Dependency jboss-javaee is not always complete, so if you are for example using standard JAX-WS you will have to add that additionally:
<dependency>
    <groupid>org.jboss.ws.native</groupid>
    <artifactid>jbossws-native-jaxws</artifactid>
    <scope>provided</scope>
</dependency>

And if you are programming MBeans they are not at all defined in the jboss-as-component-matrix, so you will have to completely add them with version:

<dependency>
    <groupid>org.jboss.jbossas</groupid>
    <artifactid>jboss-as-system-jmx</artifactid>
    <version>${jbossas.version}</version>
    <scope>provided</scope>
</dependency>

Well nothing is perfect but with this way the dependency should be a little more clearer and easier to maintain.

Handling Java Enterprise Dependency (javaee) with Maven

Almost all software development today is made with some building tool and the major one out there is Maven. But Sun and now Oracle have not made life simple for programmers that wish to use Java Enterprise Dependency to Maven. And the reason for that is the Java Enterprise API that is submitted to Maven Central Repository is good for compiling but not for execution and one example of execution is testing! And I believe that most programmers out there today want to develop there code in a more or less test driven way. And that is then hinder.

So for Java EE 5 there is the following Maven Dependency:
<dependency>     
    <groupid>javaee</groupid> 
    <artifactid>javaee-api</artifactid>
    <version>5</version>
    <scope>provided</scope> 
</dependency>

And for Java EE 6:
<dependency>     
    <groupid>javax</groupid>
    <artifactid>javaee-api</artifactid>
    <version>6.0</version>
    <scope>provided</scope>
</dependency>

NOTE that the groupId has also changed, which also is not good. Since the new Maven Dependency will be harder to locate when browser a Maven Repository, but also harder for a programmer that wish to upgrade and only wish to increase the version field and nothing else.

So when using the javaee dependency you will typically end up with a following error:
java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file

So what is you option? There is two solution
  1. Keep the standard dependency and add the container specific dependency with test scope.
  2. Leave the path with compiling against the standard API and directly using the concrete container dependency.
The first option is not very compelling because it makes the Maven pom.xml file even longer with a lot of testing dependency.

The second one is also not very compelling since you want to develop generic code and the easiest way to uphold that, especially if you have less experienced programmers in your team, is not to have the concrete container classes at all in the class path when compiling your code.

Conclusion: I have giving up for a long time ago, trying to keep your code generic and in my next blog I will show you how to best use the JBoss EE dependency.
http://magnus-k-karlsson.blogspot.se/2012/04/managing-java-enterprise-dependency.html

March 20, 2012

Memory Profiling Tool with Allocation Stack Trace

Hunting down memory consuming code, cannot be done without a good tool. Because guising which method or code block that consumes most memory, is at least according to me, almost impossible.

And one good tool that comes for free is Visual VM (http://visualvm.java.net/) If you are running Windows and Java SDK you already have it installed under
$ %JAVA_HOME%/bin/jvisualvm

And if you are running Ubuntu, simply install with:
$ sudo apt-get install visualvm

The tool is quite straight forward. You can see working thread and do thread dump to see what each thread is momentarily is doing, etc. And from the Profile tab you can perform memory profiling, but to see allocations stack trace you have to change the default settings.

March 9, 2012

Syslog client in Java that implements RELP, TCP, SSL/TLS, Caching and Resending

In one of my previous project we had the need of logging message in a secure way, we also needed to be sure that each message was really transmitted and if not sent successfully, should that really be detected.

When I started I thought there must be someone out there that have solved something similar or there exist a product that did this. Be after searching the web I came up with only this:

Log4J do support Syslog (org.apache.log4j.net.SyslogAppender) but is based on java.net.DatagramSocket which uses UDP, which is not a reliable transport protocol. I also looked at other common logging libraries, but they also do not support a TCP based Syslog Appender.

So I started of extended existing SocketAppender to talk Syslog instead. This worked, but then I realized that just having a client talking TCP does not make it reliable. The java.net.Socket.getOutputStream().write() will not throw Exception even if you stop the Syslog after successfully opening a Socket. Socket write operation is not a blocking operation and will not wait for any success message. You might now argue that a socket.getOutputStream().flush() will solve this problem, but as the Javadoc API points out, the flush operation does not guarantee that actual operating system socket will be flushed. “... it does not guarantee that they are actually written to a physical device such as a disk drive. ” [http://docs.oracle.com/javase/7/docs/api/java/io/OutputStream.html#flush%28%29]

So this was the background when I started to look at RELP, Reliable Event Logging Protocol [http://www.librelp.com/relp.html. Using the RELP protocol on top of the Syslog protocol really seemed to solve my problems. The only problem was that I could not find any Java implementation. [http://lists.adiscon.net/pipermail/relp/2010-October/000026.html] The closest project I could find was http://syslog4j.org/ but it does not support RELP.

After happily got my first Syslog Appender working using TCP and RELP. The next problem occurred when we also needed to protect the transport data. Fine I thought, just change my implementation to use a javax.net.ssl.SSLSocket instead of java.net.Socket. But the problem is the current librelp implementation does not support SSL/TLS. “The RELP transport can currently not be protected by TLS.” [http://www.rsyslog.com/doc/rsyslog_tls.html] And the only solution provided was to use a stunnel. Which works.

The last problem to solve was to make my Syslog TCP RELP Appender cache instead of sending Exception up, when communication fails. This was quite straightforward and the only challenge was to make my implementation threadsafe.

There has been discussion of making the solution open source, but the main problem right now is the lack of time.

March 7, 2012

Managing Multiple Java Installation on Ubuntu 11.10

In earlier blog I have discussed how to install Oracle Java 7 JDK (http://magnus-k-karlsson.blogspot.com/2012/01/how-to-install-oracle-jdk-on-ubuntu-11.html), but several application is not compatible with Java 7. And this was the case for me when running JBoss. So in this blog I will show you how to manage several Java installation on the same Ubuntu 11.10 computer.

Instead of changing symbolic link for /usr/bin/java there is a tool for you that does that consistently.

$ sudo update-alternatives --config java

There are 3 choices for the alternative java (providing /usr/bin/java).

Selection    Path                                      Priority   Status
------------------------------------------------------------
* 0            /usr/lib/jvm/java-7-oracle/bin/java        1063      auto mode
1            /usr/lib/jvm/java-6-openjdk/jre/bin/java   1061      manual mode
2            /usr/lib/jvm/java-6-sun/jre/bin/java       63        manual mode
3            /usr/lib/jvm/java-7-oracle/bin/java        1063      manual mode

Press enter to keep the current choice[*], or type selection number: 2
update-alternatives: using /usr/lib/jvm/java-6-sun/jre/bin/java to provide /usr/bin/java (java) in manual mode.


$ java -version
java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
Java HotSpot(TM) 64-Bit Server VM (build 20.1-b02, mixed mode)