Saturday, June 16, 2012

Install Oracle JDK 7 on Ubuntu

Update: while the method below is still a possibility (and people running Linux are usually not afraid to go the extra mile to have their system running exactly as they want), there is of course a much, much simpler way to accomplish the same: using the PPA from the "WebUpd8" team, your Oracle JDK is installed and kept up-to-date in a breeze.

Just follow the instructions on https://launchpad.net/~webupd8team/+archive/ubuntu/java!



Since I've been installing Java for development purposes a few times now on different machines running Ubuntu and had to look up how to do that each time (my attention span obviously is too short to remember properly), I've decided to make a blog entry out of it.

So the following steps will guide you through the process:

1) Download the JDK from Oracle
Go to the JDK download page and choose the version you need or want. You have to accept the agreement and you will want to choose the package for Linux in the compressed tarball format (Make sure you get the correct version corresponding to your Ubuntu installation; I got the 64-bits version, so that's jdk-[version]-linux-x64.tar.gz; for 32-bits you'd need the one with -i586 in the name).
At the time of this writing, the newest version was JDK7u5, but these guidelines should work on any 'modern' JDK.

Note: if you're interested in developing JavaFX, unlike the Windows and Mac OS packages, the Linux JDK doesn't contain the JavaFX SDK. You'll need to get a 'developer preview' here, and to be able to download it I had to log in with my (free) Oracle account.

2) Extract the package
You can use the file manager, right-click on the package and choose 'Extract here'.
Alternatively, if you insist on using the command line, use (assuming you're in the directory the package was downloaded to):
tar -xvf jdk-[version]-linux-x64.tar.gz

3) Move the extracted package to the right directory
The JDK should be moved to the place where all the libraries reside, so first you create a logical path and then you move the package:
sudo mkdir -p /usr/lib/jvm/jdk1.7.0

sudo mv jdk1.7.0_05/* /usr/lib/jvm/jdk1.7.0/
(You'll be prompted for your password to be able to perform the sudo commands.)

4) Enable the JDK
Now the system needs to be able to find the JDK, more specifically the binaries that can be run: the main Java laucher, the compiler and the Web Start launcher.
sudo update-alternatives --install "/usr/bin/java" "java" "/usr/lib/jvm/jdk1.7.0/bin/java" 1
sudo update-alternatives --install "/usr/bin/javac" "javac" "/usr/lib/jvm/jdk1.7.0/bin/javac" 1
sudo update-alternatives --install "/usr/bin/javaws" "javaws" "/usr/lib/jvm/jdk1.7.0/bin/javaws" 1

5) Make the new JDK the default choice - if necessary
If the JDK you just installed is the only one on your system, then this step is not required. If you're not working on a freshly installed machine, this will most likely not be the case, and you'll need to configure the settings so the new JDK is picked instead of the other ones.
sudo update-alternatives --config java
This will bring up an overview of the available alternatives, indicating the current default. Just enter the number that is printed in front of the launcher from the fresh install.
Rinse and repeat for the compiler and Web Start launcher:
sudo update-alternatives --config javac
sudo update-alternatives --config javaws
You can check whether all went well by retrieving the version of the Java installation:
java -version
and you should see something like:
java version "1.7.0_05"
Java(TM) SE Runtime Environment (build 1.7.0_05-b05)
Java HotSpot(TM) 64-Bit Server VM (build 23.1-b03, mixed mode)
And you're done!

Note: if you're getting a “No such file or directory” message instead of the Java version and you've made sure the symbolic links are correct and the files are there, chances are that you've installed a 32-bits JDK on a 64-bits OS. Remove the directory under /usr/lib/jvm/jdk1.7.0/ and start again from step 1, choosing the right package this time.

Wednesday, April 25, 2012

Customizing the JNDI name(s) of the JBoss 5.1 ConnectionFactory


Customizing the JNDI name(s) of the JBoss 5.1 ConnectionFactory takes the following steps:

- Change or add the binding name(s) in the [server]/deploy/messaging/connection-factories-service.xml file:

   
      jboss.messaging:service=ServerPeer
      jboss.messaging:service=Connector,transport=bisocket
      jboss.messaging:service=PostOffice

      
         
            /ConnectionFactory
            /XAConnectionFactory
            java:/ConnectionFactory
            java:/XAConnectionFactory
            /YOUR_JNDI_NAME_HERE
         
      
  

Same goes for the clustered connection factory (defined in the same file just under the other one).

- Only if necessary (i.e. changed in the above) adjust the corresponding reference in the JMS datasource file ([server]/deploy/messaging/jms-ds.xml, this is the original file referencing the standard java:/XAConnectionFactory reference):

   
      DefaultJMSProvider
      org.jboss.jms.jndi.JNDIProviderAdapter
      java:/XAConnectionFactory
      java:/XAConnectionFactory
      java:/XAConnectionFactory
   

Now you can use whatever name you want to bind the connection factory to from within your application!

Tuesday, August 16, 2011

Update on the Quartz caveat

My previous post explained how to use Quartz on JBoss 5.1, and gave you a heads-up about the way JBoss properties are mangled on Windows platforms.

Kudos to the guys at Terracotta, who picked up quickly on the corresponding issue I filed and included a fix in the very next release (which is 2.1, released September 16th)!

Monday, July 18, 2011

'External' Quartz on JBoss 5.1

On our current project, we have the requirement to be able to run our application on more than JBoss AS alone. When confronted with the need to schedule certain tasks, we considered a few options:
  • Use EJB timers: Due to the nature of the tasks (e.g. interdependencies) this mechanism is not suitable - it's simply just not sophisticated enough.
  • Use the Quartz functionality provided along with the JBoss distribution: While this may do exactly what we need, it wouldn't be portable to app servers from other vendors.
So the decision was made to use Quartz, not as readily available from JBoss but as an add-on library ('external', if you will). I found a couple of articles that pointed me in the right direction:
We used Quartz version 2.0.2 - the latest and greatest at the time I write this - and since Maven is our build tool of choice, the following dependency pulls all required libs into our project:

  org.quartz-scheduler
  quartz-jboss
  2.0.2
  provided
 
We use provided scope here since we won't be including Quartz in our project's deliverables; instead we put such dependencies on our server explicitly. Either approach would work, though.

1) Clean up your installation.

So, the first job at hand is to remove the Quartz artifacts from our JBoss installation. I guess it makes sense to prevent different versions from showing up in your classpath. The files to be removed are:
  • ${jboss.home.dir}/common/lib/quartz.jar
  • ${jboss.home.dir}/server/[SERVER_NAME]/deploy/quartz-ra.rar (in EAP this is an exploded RAR, so remove the directory)
Before deleting anything from the common/lib directory, be sure that there aren't any other servers running from the same AS installation that need that file!

2) Add the required Quartz libraries to you server.

The following file should be in place after this step:
  • ${jboss.home.dir}/server/[SERVER_NAME]/lib/quartz-all-2.0.2.jar
That's right. Just one jar, very convenient - and the added bonus is that this already contains the stuff that's needed for deployment in other app servers, so no need to have different dependencies in different deployments.

Note that this file is not downloaded if you include the dependencies through Maven as indicated above, you have to download the full distribution to get it.

3) Add an MBean to the JBoss configuration.

The following is a simple example of a Quartz MBean configuration:

  
   Quartz
   
    org.quartz.scheduler.instanceName = DefaultQuartzScheduler
    org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
    org.quartz.threadPool.threadCount = 5
    org.quartz.threadPool.threadPriority = 4
    org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
   
  
 
If you use this, no extra DataSource needs to be configured and Quartz keeps its jobs in memory. For more specifics on the configuration possibilities (there are a lot!), see http://www.quartz-scheduler.org/docs/configuration/.

Put the XML above in a x-service.xml file in your server's deploy dir, like e.g.:
  • ${jboss.home.dir}/server/[SERVER_NAME]/deploy/quartz-service.xml
4) Point Quartz at the jobs you want done.

Obviously it now is possible to use Quartz from code inside deployed applications. Just retrieve the scheduler from JNDI like so:
InitialContext ctx = new InitialContext();
 Scheduler scheduler = (Scheduler) ctx.lookup("Quartz");
But for our purpose this just isn't good enough, we want to be able to schedule tasks from configuration files. To accomplish that, we need to perform a number of steps:

a) Enable the Quartz plugin that reads jobs and triggers from an indicated XML file. This is done by adding the following properties to the configuration shown in step 3):
org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
   org.quartz.plugin.jobInitializer.fileNames = ${jboss.server.home.dir}/conf/quartz-jobs.xml
   org.quartz.plugin.jobInitializer.scanInterval = 120
For details on this plugin see http://www.quartz-scheduler.org/api/2.0.0/org/quartz/plugins/xml/XMLSchedulingDataProcessorPlugin.html.

b) Create a class that implements the org.quartz.Job interface for each such a task. This interface exposes exactly one method, void execute(JobExecutionContext ctx), which is called when the job is triggered.

c) Provide the quartz-jobs.xml file that is indicated in the extra configuration in step a) (the file name and path can be adjusted to your liking) with the appropriate timing to start your jobs. For our tasks we use Cron-like jobs, with the Quartz CronTrigger (see http://www.quartz-scheduler.org/api/2.0.0/org/quartz/CronTrigger.html). An example configuration is:

  
  *  
    * 
  
    true
    false 
  
  
  
   
    TestJob
    com.acme.quartz.TestJob
   

   
    
     TestCronTrigger
     TestJob
     0 0 3 ? * MON-FRI
    
   
      

 
In this example the task executed by the com.acme.quartz.TestJob class is triggered at 3:00 AM on weekdays.

One last CAVEAT: On Windows, the ${jboss.server.home.dir} expression resolves to a String that contains backward slashes ('\') instead of forward slashes as path delimiter. The way the Quartz extension for JBoss reads in the properties is not able to cope with that, so you may need to provide a full path explicitly for any file names.

Friday, January 14, 2011

Use Apache as a secure (reverse) proxy for JBoss 5 AS/EAP

This task can be divided into two independent components (configure Apache to use SSL, set up Apache as a reverse proxy for JBoss) and a single step to make those two work together. The guidelines below have been successfully tested on an Apache 2.2.17/JBoss EAP 5.1.0.GA combination, the latter using Tomcat native libs, on a single server.


Part 1: Use SSL for access to Apache

1) Download and install the Apache Httpd server (version 2.2.6 or higher, 2.2.17 is the current). The folder in which the server is installed is referred to as APACHE_HOME further on.

2) In APACHE_HOME/conf/httpd.conf, un-comment the following lines:
    LoadModule ssl_module modules/mod_ssl.so

    Include conf/extra/httpd-ssl.conf
Then comment the following one (to restrict access without SSL):
    #Listen 80
3) Put your certificate and key in the APACHE_HOME/conf folder, and (if necessary) change the names in APACHE_HOME/conf/extra/httpd-ssl.conf entries to match:
    SSLCertificateFile "[APACHE_HOME]/conf/server.crt"
    SSLCertificateKeyFile "[APACHE_HOME]/conf/server.key"
If you don’t have a CA certificate, you can create a self-signed certificate for testing purposes, see e.g. the OpenSSL FAQ how to do so. An OpenSSL executable is provided in the APACHE_HOME/bin folder.

Remark: On Windows platforms it is not possible to use the SSLPassPhraseDialog-parameter (in httpd-ssl.conf) with the default value ‘builtin’. The simplest (albeit not the safest) solution is to remove the passphrase from the key, removing the need for Apache to ask for it at startup.

4) (Re-)start the Apache server and test whether it works as expected… and don’t forget the ‘https://’!

For an extensive explanation of the SSL configuration possibilities see Apache Module ssl_mod.


Part 2: Set Apache up as a reverse proxy for JBoss

1) Download the mod_jk connector (version 1.2.15 or higher, 1.2.31 is the current), rename the ‘mod_jk-1.2.[*]-httpd-2.2.x.so’ file to ‘mod_jk.so’ and move it to the APACHE_HOME/modules folder.

2) Add the following line to APACHE_HOME/conf/httpd.conf:
    Include conf/mod-jk.conf
3) Create a new file in APACHE_HOME/conf with the name ‘mod-jk.conf’, and fill it with:
    LoadModule jk_module modules/mod_jk.so

    JkWorkersFile conf/workers.properties

    JkLogFile logs/mod_jk.log
    JkLogLevel info
    JkLogStampFormat "[%a %b %d %H:%M:%S %Y]"
    JkRequestLogFormat "%w %V %T"

    JkOptions +ForwardKeySize +ForwardURICompatUnparsed -ForwardDirectories

    # Mount your applications
    ###JkMount /application/* loadbalancer
    # Mount all URLs:
    JkMount /* node1

    # You can addionally use external file for mount points.
    ###JkMountFile conf/uriworkermap.properties
    # Mount file reload check interval in secs (0 = turned off).
    ###JkMountFileReload 60

    # Add shared memory. Used only on unix platforms. The shm file is used by balancer and status workers.
    ###JkShmFile run/jk.shm

    # Add jkstatus for managing runtime data:
    <Location /jkstatus/>
        JkMount status
        Order deny,allow
        Deny from all
        Allow from 127.0.0.1
    </Location>
When not all requests are to be redirected to node1 the line starting with ‘JkMount’ must be adjusted. Furthermore it is possible to use a separate properties file (using ‘JkMountFile’, with entries following the pattern ‘URL=worker’, e.g. ‘/jmx-console=node1’) if you need a more extensive redirection scheme.

In the configuration above the access to the status manager (worker with ID ‘status’) is restricted to clients running on the same host, just for illustrative purposes.

See the Tomcat connector reference for further details and possibilities.

4) Create a new file in APACHE_HOME/conf named  ‘workers.properties’,  and put the following in it:
    # Define list of workers that will be used for mapping requests

    # Define Node1
    # modify the host as your host IP or DNS name.
    worker.node1.type=ajp13
    worker.node1.host=localhost
    worker.node1.port=8009
    worker.node1.ping_mode=A
    #worker.node1.connection_pool_size=10 # Only if the number of allowed connections to the Httpd is higher than maxThreads in JBoss server.xml.
    #worker.node1.lbfactor=1 # Only used for a member worker of a load balancer.
    # For non-loadbalanced setup with a single node:
    worker.list=node1

    # Define Node2
    # modify the host as your host IP or DNS name.
    #worker.node2.type=ajp13
    #worker.node2.host= node2.mydomain.com
    #worker.node2.port=8009
    #worker.node2.ping_mode=A
    #worker.node2.connection_pool_size=10
    #worker.node2.lbfactor=1

    # Load-balancing behaviour
    #worker.loadbalancer.type=lb
    #worker.loadbalancer.balance_workers=node1,node2
    #worker.loadbalancer.sticky_session=Off # Enabled by default.
    #worker.list=loadbalancer

    # Status worker for managing load balancer
    worker.status.type=status
    worker.list=status
Most lines above are commented out, since we’re aiming for a configuration for a single node without loadbalancing. It is straightforward to add more nodes, with or without loadbalancing; just pay attention to the fact that with loadbalancing the worker.list should not refer to the separate nodes but only to the loadbalancer worker.

5) For each (JBoss-)node a ‘jvmRoute’ attribute  must be added to the <Engine>-element in JBOSS_HOME/server/[configuration]/deploy/jbossweb.sar/server.xml, using the corresponding name from the mod_jk-configuration as a parameter:
    <Engine name="jboss.web" defaulthost="localhost" jvmroute="node1">
And for JBoss AS/EAP version 5 and above that is all that is required!

6) If you didn't configure Apache to use SSL, you can now (re-)start the JBoss en Apache servers and test whether the redirecting functions as expected…
If you did configure SSL for Apache, hang on just a bit more...


Part 3: Combining the twee solutions above

To be able to access Apache using SSL after which the request is passed to the JBoss instance over AJP, one last adjustment is required:

1) Move the JkMount directives from the APACHE_HOME/conf/mod-jk.conf file to the APACHE_HOME/conf/extra/httpd-ssl.conf file, and make sure they’re within the <VirtualHost> tags:
    <VirtualHost _default_:443>

    […]

    JkMount /* node1
    <Location /jkstatus/>
        JkMount status
        Order deny,allow
        Deny from all
        Allow from 127.0.0.1
    </Location>

    </VirtualHost>
After a restart of the Apache server the pages served by JBoss will be available over HTTPS from Apache (port 443).

Be aware that they are also still available over HTTP from JBoss directly (on port 8080), since the configuration above didn’t remove that (default) situation. To accomplish that, you should comment the HTTP connector entry in the server.xml file of jbossweb.sar.

Wednesday, December 29, 2010

No, labels in Java are not 'evil'... at least not per se!

Last week I got into an argument with some colleagues about the use of labels in Java for escaping nested loops. The general consensus was some along the line of "using break or continue with a label is evil, because it is a goto". While I feel the construct should be applied with care and many instances in which it could be applied a refactoring into e.g. a call to a separate method makes sense, it certainly has its use and cannot simply be deemed evil.

I can think of a couple of sources for the misconception:
  • When Dijkstra published his letter in Communications of the ACM "Go To Statement Considered Harmful" way back in 1968 this led to a lot of controversy too, and somehow only the title of the letter has stuck with a lot of people - but not its original contents nor its true intent.
  • Java has the reserved keyword goto, but doesn't allow its use. James Gosling outlawed it, so it must be bad - nevertheless he did put in the labels.
So I feel that not getting the whole picture is responsible for such misinformedness in some (or maybe even: many) programmers. But hey, don't just take my word for it!

In his book 'Thinking in Java' Bruce Eckel explains that "In Dijkstra’s “goto considered harmful” paper, what he specifically objected to was the labels, not the goto. He observed that the number of bugs seems to increase with the number of labels in a program. Labels and gotos make programs difficult to analyze statically, since it introduces cycles in the program execution graph. Note that Java labels don’t suffer from this problem, since they are constrained in their placement and can’t be used to transfer control in an ad hoc manner. It’s also interesting to note that this is a case where a language feature is made more useful by restricting the power of the statement."

In a (lengthy and by now five-year-old) retrospective of Dijkstra's paper, David Tribble illustrates that goto-like constructs are business-as-usual in modern programming languages without it being apparent al the time, and that constructs mentioned by Dijkstra include not only labels for exiting loops, but also e.g. exception handling (try-catch-finally blocks).
Furthermore he also reaches the conclusion that "Dijkstra's belief that unstructured goto statements are detrimental to good programming is still true. A properly designed language should provide flow control constructs that are powerful enough to deal with almost any programming problem. By the same token, programmers who must use languages that do not provide sufficiently flexible flow control statements should exercise restraint when using unstructured alternatives. This is the Tao of goto: knowing when to use it for good and when not to use it for evil."

Dustin Marx puts it nicely when he says "The more I work in the software development industry, the more convinced I become that there are few absolutes in software development and that extremist positions will almost always be wrong at one point or another. I generally shy away from use of goto or goto-like code, but there are times when it is the best code for the job. Although Java does not have direct goto support, it provides goto-like support that meets most of my relatively infrequent needs for such support."


Now I'm not saying that the above is the conclusive evidence that proves my point. But you may interpret it as an incentive to be a little more openminded when it comes to certain 'conventional wisdoms' surrounding programming...


Update: If you take a look e.g. at this nice article on Java bytecode, specifically the bit about exception handling, you can see what's happening under the hood. That's right, those are just plain vanilla gotos at work when you use a try-catch block!

Wednesday, November 17, 2010

Uploading jBPM .par files (from a repository)

Once you've passed the testing cycles during development, you want to make sure that the processes that get deployed onto the production environment are indeed versions that were released according to your formal build procedure - if you have such in place of course.

In our case, that means that the officially released processes are available from a Maven repository. Now there's nothing wrong with retrieving a newly released process archive and using e.g. the jBPM console to upload it. That is, if there's just one such .par file to upload.

My current project produces no less than 16 process archives, one of which is referenced in multiple locations - so it is not uncommon to have more than 20 process instances started during the course of a single request we're processing.

Now regardless of the question whether we chose the right granularity for our processes (which I think we did, of course), this turned into quite some work for each deployment cycle, keeping track of which .par file was deployed and whether it was in the correct sequence (we're not using late binding for sub-processes). Performing this task had become too error-prone to allow it for the production environment.

Ant to the rescue?

The user guide states that there are three ways to deploy the process archives (they forget about the jBPM console altogether there):
  • The process designer tool; an Eclipse plug-in that is part of JBoss Tools. This is of course not a real option, since we want to be able to deploy process archives without having to start up an IDE.
  • The org.jbpm.ant.DeployProcessTask; an Ant task available from the regular jBPM jar file. While an Ant build actually is a good option for a command-line alternative, this particular task is simply too much: it starts up a complete jBPM context for uploading the process directly to the database, and as such requires all of the applicable configuration. I prefer to have as little direct database access from external hosts as possible (e.g. for security considerations), and this approach doesn't accomplish that.
  • Programmatically; using the jBPM API directly. That is basically just more complex than using the Ant task, so that's not the way to go either (in this case).
So unfortunately these suggestions don't give us the ease-of-use that the jBPM console did, just selecting the .par file and clicking the 'Deploy' button, and we had to search a little further.

Reuse the input method of the designer

A closer look at the GPD designer plug-in shows that its upload functionality is little more than an HTTP client, calling the POST method of the ProcessUploadServlet of the jBPM console. This servlet then uses the functionality of the jBPM API (as mentioned above for the Ant task and the programmatic approach). This entrance into the jBPM deployment is exactly what we need: it's simple in just requiring the .par file to be entered, any database interaction is taken care of by the servlet, any security issues can be addressed by the deployment of the console (see e.g. how that's done in the SOA platform).

So, using Apache's HttpClient library I finally came up with something like the following:
package org.jbpm.par;

import java.io.InputStream;
import java.net.URL;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.ContentBody;
import org.apache.http.entity.mime.content.InputStreamBody;
import org.apache.http.impl.client.DefaultHttpClient;

public class ProcessUploader {
    public static void main(String[] args) {
        HttpClient client = null;
        try {
            // Get the input parms: first the file name, then the URL String for its location (in the repo).
            String fileName = args[0];
            URL url = new URL(args[1]);

            // Prepare the request.
            HttpPost request = new HttpPost("http://localhost:8080/jbpm-console/upload");
            ContentBody body = new InputStreamBody(url.openStream(), "application/x-zip-compressed", fileName);
            MultipartEntity entity = new MultipartEntity();
            entity.addPart("bin", body);
            request.setEntity(entity);

            // Execute the request.
            client = new DefaultHttpClient();
            HttpResponse response = client.execute(request);

            // You can examine the the response further by looking at its contents:
            InputStream is = response.getEntity().getContent(); // And e.g. print it to screen...
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if (client != null) {
                // Clean up after yourself.
                client.getConnectionManager().shutdown();
            }
        }
    }
}
While this simple example takes a single URL for a .par file (along with the corresponding file name) on the command line, we'll be using the same principle with a standard properties file listing all of the URLs for our process archives and looping through that list executing a request for each file. And these URLs will be pointing to our Maven repository, of course, allowing us to configure the correct versions for each release.

Note that the URL for the upload servlet is hard-coded in the example; if you're uploading your .par files from a different host, you'd want to configure the host on which jBPM runs differently than 'localhost', of course.