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