Tuesday, May 31, 2011

Mac OS X Java launchd (inetd) Applications

While I was creating my daemon examples for my previous blog entry, I created a plist file for executing launchd based applications. The convention is to name the plist file to match the name of the main application. In this example, it is com.bluelotussoftware.examples.Daemon. Place the file int the ~/Library/LaunchAgents directory.
Here is the file: com.bluelotussoftware.examples.Daemon

com.bluelotussoftware.examples.Daemon


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN
http://www.apple.com/DTDs/PropertyList-1.0.dtd >
<plist version="1.0">
    <dict>
        <key>Label</key>
        <string>com.bluelotussoftware.examples.Daemon</string>
        <!-- Program key is not necessary for Java -->
        <!--
        <key>Program</key>
        <string>/usr/bin/java</string>
        -->
        <key>ProgramArguments</key>
        <array>
            <string>/usr/bin/java</string>
            <string>-jar</string>
            <!-- MODIFY THIS TO POINT TO YOUR EXECUTABLE JAR FILE -->
            <string>/Users/jyeary/Desktop/JavaDaemonExample.jar</string>
        </array>
        <key>OnDemand</key>
        <true/>
        <key>RunAtLoad</key>
        <false/>
        <key>KeepAlive</key>
        <false/>
        <!-- MODIFY FOR YOUR ENVIRONMENT -->
        <key>StandardErrorPath</key>
        <string>/Users/jyeary/Desktop/err.log</string>
        <key>StandardOutPath</key>
        <string>/Users/jyeary/Desktop/out.log</string>
        <key>WorkingDirectory</key>
        <string>/Users/jyeary/Desktop</string>
    </dict>
</plist>

How to exercise your Daemons - Callable, Future, and ExecutorService

Mac OS X logoImage via Wikipedia
In a previous post, I mentioned how to add a shutdown hook to your application. This is great for the case where you need to do some cleanup prior to exiting. The example below shows how to convert your class to work like a daemon on UNIX, or a service on Windows. I will not go into details on how to create a UNIX, or Windows service. I will provide a StartupItem example for Mac OS X, or a modern inetd plist for launchd.

In the example classes below, I create a value holder object, a Callable<ValueHolder>, a Future<ValueHolder>, an ExecutorService which uses a SingleThreadExecutor. The concurrency libraries are from java.util.concurrent which is based on the original work done by Doug Lea, et. al. These classes make doing Thread based programming much simpler.

Here are the relevant files for the application:
JavaDaemonExample.zip (NetBeans 7.0 project)
JavaDaemonStartupItem.zip (This is for OS X 10.4 or less. It will work on 10.5+, but is not preferred)
com.bluelotussoftware.examples.Daemon (This is the inetd plist for launchd 10.5+ preferred)

Before we get to the code, the Mac OS X daemon controls must be modified to match your environment.

The com.bluelotussoftware.examples.Daemon plist file needs to modified to point to the jar file to execute. This is for Leopard, and Snow Leopard.
  1. To install it, place it in the ~/Library/LaunchAgents directory.
  2. From a command prompt, type:
    launchctl load -w /Users/jyeary/Library/LaunchAgents/JavaDaemonStartupItem/com.bluelotussoftware.examples.Daemon
    This loads it.
  3. To execute from launchctl:
    root:$ launctl
    launchd% start com.bluelotussoftware.examples.Daemon
    launchd% list
    launchd% quit
    root:$

Alternatively, you can use the JavaDaemonStartupItem.
  1. Modify the JavaDaemonStartupItem script to match your environment.
  2. Place the files in the /Library/StartupItems directory.
  3. Change permissions:
    sudo chown -R root:wheel JavaDaemonStartupItem
  4. Execute the application using:
    sudo /sbin/SystemStarter start "Java Daemon Example"

This is the main code Example:

Daemon.java


/*
 * Copyright 2011 John Yeary <jyeary@bluelotussoftware.com>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * $Id: Daemon.java 355 2011-05-31 21:05:01Z jyeary $
 */
package com.bluelotussoftware.examples;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Main executable daemon class.
 * @author John Yeary <jyeary@bluelotussoftware.com>
 * @version 1.0
 */
public class Daemon {

    private static final Logger logger = Logger.getLogger(Daemon.class.getName());


    /**
     * Default no-argument constructor.
     */
    public Daemon() {

    }

    /**
     * Main execution entry point.
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        try {
            /* Create a file handler which is used to log output. This
             * becomes vitally important since we close the System.out,
             * System.err, and System.in streams next.
             */
            Handler handler = new FileHandler(Daemon.class.getName() + ".log");
            logger.addHandler(handler);
        } catch (IOException ex) {
            ex.printStackTrace(System.err);
        } catch (SecurityException ex) {
            ex.printStackTrace(System.err);
        }

        logger.log(Level.INFO, "Closing streams");
        closeDefaultStreams();
        logger.log(Level.INFO, "Fetching ExecutorService");
        final ExecutorService executorService = Executors.newSingleThreadExecutor();
        logger.log(Level.INFO, "Adding Shutdown Hook");
        Runtime.getRuntime().addShutdownHook(new Thread() {

            @Override
            public void run() {
                shutdown(executorService);
            }
        });

        logger.log(Level.INFO, "Submitting CallableDaemon");
        Future<ValueHolder> future = executorService.submit(new CallableDaemon());
        logger.log(Level.INFO, "Waiting for results...");

        try {
            StringBuilder sb = new StringBuilder();
            sb.append("Results: ");
            sb.append(Arrays.toString(future.get().getDates().toArray()));
            logger.log(Level.INFO, sb.toString());
        } catch (InterruptedException ex) {
            logger.log(Level.SEVERE, null, ex);
        } catch (ExecutionException ex) {
            logger.log(Level.SEVERE, null, ex);
        }
        logger.log(Level.INFO, "Shutting down ExecutorService normally.");
        /* Call to shutdown executor service, otherwise the application blocks
         * and waits for another Runnable to be submitted. You can verify this in the
         * debugger, or by submitting another Runnable.
         */
        executorService.shutdown();
    }

    //TODO Need to verify that this is necessary for Windows systems.
    /**
     * This method closes {@code System#out}, {@code System#err}, and {@code System#in}
     * streams. This prevents premature shutdown from closure of terminal.
     */
    private static void closeDefaultStreams() {
        System.out.close();
        System.err.close();
        try {
            System.in.close();
        } catch (IOException ex) {
            logger.log(Level.WARNING, "Closing System.in() caused an Exception", ex);
        }
    }

    /**
     * Shutdown hook which calls {@code java.util.concurrent.ExecutorService#shutdownNow()}
     * @param executorService the executor which we want to attach to, and shutdown.
     */
    private static void shutdown(ExecutorService executorService) {
        logger.log(Level.INFO, "Executing shutdown hook");
        List<Runnable> runnables = executorService.shutdownNow();
        logger.log(Level.INFO, "The following items were awaiting execution when the daemon shutdown",
                Arrays.toString(runnables.toArray(new Runnable[runnables.size()])));
    }
}

This is the Callable<ValueHolder>:

CallableDaemon.java


/*
 * Copyright 2011 John Yeary <jyeary@bluelotussoftware.com>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * $Id: CallableDaemon.java 355 2011-05-31 21:05:01Z jyeary $
 */
package com.bluelotussoftware.examples;

import java.util.Date;
import java.util.concurrent.Callable;

/**
 * An example <code>Callable</code> implementation which executes and
 * waits. Every execution adds a <code>Date</code> to a <code>ValueHolder</code>.
 * On <code>call</code> completion, it returns the <code>ValueHolder</code>.
 * @author John Yeary <jyeary@bluelotussoftware.com>
 * @version 1.0
 */
public class CallableDaemon implements Callable<ValueHolder> {

    private int counter;
    private int iterations = 12;

    /**
     * Default no-argument constructor.
     */
    public CallableDaemon() {
    }

    /**
     * Constructor which sets the number of iterations.
     * @param iterations integral value which sets the number
     * of iterations to be executed.
     */
    public CallableDaemon(int iterations) {
        this.iterations = iterations;
    }

    /**
     * {@inheritDoc java.util.concurrent.Callable#call()}
     */
    @Override
    public ValueHolder call() throws Exception {
        ValueHolder valueHolder = new ValueHolder();
        for (; counter < iterations; counter++) {
            valueHolder.getDates().add(new Date());
            synchronized (this) {
                this.wait(5000);
            }
        }
        return valueHolder;
    }
}

ValueHolder


/*
 * Copyright 2011 John Yeary <jyeary@bluelotussoftware.com>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * $Id: ValueHolder.java 355 2011-05-31 21:05:01Z jyeary $
 */
package com.bluelotussoftware.examples;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * A value holder object.
 * @author John Yeary <jyeary@bluelotussoftware.com>
 */
public class ValueHolder {

    private List<Date> dates;

    /**
     * Default no-argument constructor.
     */
    public ValueHolder() {
        dates = new ArrayList<Date>();
    }

    /**
     * Returns a {@code List<Date>} objects contained in the <code>ValueHolder</code>.
     * The method is synchronized because it can be used to add values to the internal
     * <code>List</code>.
     * @return {@code List<Date>} objects contained in the <code>ValueHolder</code>.
     */
    public synchronized List<Date> getDates() {
        return dates;
    }
}


Enhanced by Zemanta

Logging to a File - Using a FileHandler

Java has a built in logging mechanism. This mechanism was adding to provide logging functionality to the base Java libraries. This removes external dependencies from your project, and allows you to use logging within the base framework.

Log4J has an incredible amount functionality, but requires that you add the framework to your project and its dependencies. There is also configuration required up front to use the logging.

The default logging mechanism is very easy to use. We simply create a Logger instance from the static class. Using it is as simple as calling Logger.getAnonymousLogger();. This allows you to create an anonymous logger which is a console logger. There is no default mechanism for logging to the file system. This accomplished by using a FileHandler.

A simple sample implementation is located below. I have please note the comments. The NetBeans project is located here: ExampleLogger.zip

ExampleLogger.java


/*
 * Copyright 2011 John Yeary <jyeary@bluelotussoftware.com>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.bluelotussoftware.example;

import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author John Yeary <jyeary@bluelotussoftware.com>
 * @version 1.0
 */
public class LoggerExample {

    private static final Logger logger = Logger.getLogger(LoggerExample.class.getName());
    private FileHandler fileHandler;

    public LoggerExample() {
        /*
         * This is one option using the FileHandler in the constructor
         * for the class. This will work if we need to instantiate
         * the class before use. In the case of a class where the main()
         * method is located we should consider a separate case in
         * the main method to initialize the handler. (See below)
         */
        addFileHandler(logger);
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        logger.info("main() method called.");

        /*
         * Instantiating the class with actually create two
         * FileHandlers.
         */
        LoggerExample le = new LoggerExample();

        /*
         * Anonymous inner class method for adding a FileHandler
         * in main() method.
         */
        try {
            logger.info("Adding FileHandler");
            logger.addHandler(new FileHandler(LoggerExample.class.getName()
                    + ".main.log"));
            logger.info("Added FileHandler to Logger");
        } catch (IOException ex) {
            logger.log(Level.SEVERE, null, ex);
        } catch (SecurityException ex) {
            logger.log(Level.SEVERE, null, ex);
        }

        // Example logging.
        logger.info("Logging for fun and profit");
        logger.fine("Fine...");
        logger.finer("Finer...");
        logger.finest("Finest...");
        logger.warning("Warning...");
        logger.severe("Severe...");
        logger.info("Logging complete.");
    }

    /**
     * Add a <code>FileHandler</code> to the provided <code>Logger</code>.
     * @param logger <code>Logger</code> to add <code>FileHandler</code>.
     */
    private void addFileHandler(Logger logger) {
        try {
            fileHandler = new FileHandler(LoggerExample.class.getName() + ".log");
        } catch (IOException ex) {
            logger.log(Level.SEVERE, null, ex);
        } catch (SecurityException ex) {
            logger.log(Level.SEVERE, null, ex);
        }
        logger.addHandler(fileHandler);
    }
}
Enhanced by Zemanta

Saturday, May 28, 2011

Woodstock (Visual JSF) Calendar Binding Example

There was a post on the nbj2ee forum about binding a Woodstock Calendar to a backing bean. This is a simple example which demonstrates how to do it. The project was done in NetBean 6.7.1 and should work on NetBeans 6.5, 6.7, and 6.8 with the Visual JSF plugins installed.

WoodstockCalendarBindingExample







Enhanced by Zemanta

Friday, May 27, 2011

Application Shutdown Hook

JavaImage via Wikipedia
I was working with an application that needed to be run as a daemon. When the application is shutdown, we needed to do it in a clean manner, and release resources. So the question becomes how is it done.

Fortunately, the Runtime class provides mechanism for adding a shutdown hook. The shutdown hook code below was added to the constructor. The shutdown method is invoked when the application is shutdown, for example CTRL+C.

// add shutdown hook to stop server
        Runtime.getRuntime().addShutdownHook(new Thread() {

            @Override
            public void run() {
                shutdown();
            }
        });
    }

public void shutdown() {
// add code to cleanly shutdown service here.
}
Enhanced by Zemanta

RichFaces 3.3 (Ajax4JSF) and Apache Myfaces Tomahawk AJAX Example

I was working on an application at the office which involved mixing RichFaces 3.3 along with Apache MyFaces Tomahawk. Although some JSF frameworks claim interoperability, it is best to test them out to confirm that they will work in your specific project.

In the example application attached, I have created a facelets based application which uses Tomahawk components combined with RichFaces A4J to provide AJAX support.

It is a simple demonstration using AJAX to answer a comical question of which came first, the chicken, or the egg. Here is the example code: a4j-example.zip

index.xhtml


<?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:a4j="http://richfaces.org/a4j"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:t="http://myfaces.apache.org/tomahawk"
      >
    <head>
        <title>The Chicken or Egg Question...</title>
    </head>
    <body>
        <t:panelTabbedPane id="panelTabbedPane1" serverSideTabSwitch="true">
            <t:panelTab id="panelTab1" label="Questionable Panel">
                <h:panelGrid id="panelGrid1" columns="1">
                    <t:div id="div1">
                        <t:outputText id="outputText1" value="Which came first? #{index.value}"/>
                    </t:div>
                    <t:panelGroup id="panelGroup1">
                        <t:div id="div2" rendered="#{!empty index.value}">
                            <h:outputText value="I guess you know best don't you!"
                                          style="color: green; font-weight: bold;
                                          font-variant: small-caps; font-size: x-large"/>
                        </t:div>
                    </t:panelGroup>
                    <h:form id="form1">
                        <h:selectOneMenu id="selectOneMenu1" value="#{index.value}"
                                         valueChangeListener="#{index.selectOneMenuAction}">
                            <f:selectItems id="selectItems1" value="#{index.items}"/>
                            <a4j:support id="support1" event="onchange" reRender="div1,panelGroup1"/>
                        </h:selectOneMenu>
                    </h:form>
                </h:panelGrid>
            </t:panelTab>
            <t:panelTab id="panelTab2" label="Empty"/>
            <t:panelTab id="panelTab3" label="The Big Empty"/>
        </t:panelTabbedPane>
    </body>
</html>


Enhanced by Zemanta

Monday, May 23, 2011

Threaded Queue Example - ConcurrentLinkedQueue

We were giving interviews to some prospective developers for our team at work. One of the questions/examples we asked for was to create a multi-threaded application which has a producer thread and a consumer thread which passes messages between them.

After a couple of really bad attempts by prospects, I decided to give it a try. I have not done a lot of multi-thread applications (standalone) since most of my work has to do with applications in containers. I wondered if I could do it. Well my results are in the included application. It is just one way of doing it, but I thought I would post the cleaned-up version.

The NetBeans project can be downloaded from here: ThreadedQueueExample.zip

ThreadedQueueExample.java


/*
 * Copyright 2011 Blue Lotus Software, LLC.
 * Copyright 2011 John Yeary
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * $Id: ThreadedQueueExample.java 347 2011-05-23 12:22:29Z jyeary $
 */
package com.bluelotussoftware.thread.example;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 *
 * @author John Yeary
 * @version 1.0
 */
public class ThreadedQueueExample {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        Queue<Message> queue = new ConcurrentLinkedQueue<Message>();

        Producer p = new Producer(queue);
        Consumer c = new Consumer(queue);

        Thread t1 = new Thread(p);
        Thread t2 = new Thread(c);


        t1.start();
        t2.start();
    }
}

Producer.java


/*
 * Copyright 2011 Blue Lotus Software, LLC.
 * Copyright 2011 John Yeary
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * $Id: Producer.java 347 2011-05-23 12:22:29Z jyeary $
 */
package com.bluelotussoftware.thread.example;

import java.util.Queue;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author John Yeary
 * @version 1.0
 */
public class Producer implements Runnable {

    private static int ctr;
    private final Queue<Message> messageQueue;
    private final Random r;

    public Producer(Queue<Message> messageQueue) {
        this.messageQueue = messageQueue;
        r = new Random();
    }

    @Override
    public void run() {
        while (true) {
            produce();
            int wait = r.nextInt(5000);
            try {
                Thread.sleep(wait);
            } catch (InterruptedException ex) {
                Logger.getLogger(Producer.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    private void produce() {
        Message m = new Message(++ctr, "Example message.");
        messageQueue.offer(m);
        synchronized (messageQueue) {
            messageQueue.notifyAll();
        }
        System.out.println("Producer: " + m);
    }
}

Consumer.java


/*
 * Copyright 2011 Blue Lotus Software, LLC.
 * Copyright 2011 John Yeary
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * $Id: Consumer.java 349 2011-05-23 15:25:32Z jyeary $
 */
package com.bluelotussoftware.thread.example;

import java.util.Queue;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author John Yeary
 * @version 1.0
 */
public class Consumer implements Runnable {

    private final Queue<Message> queue;

    public Consumer(Queue<Message> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        while (true) {
            consume();
            try {
                synchronized (queue) {
                    queue.wait();
                }
            } catch (InterruptedException ex) {
                Logger.getLogger(Consumer.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    private void consume() {
        while (!queue.isEmpty()) {
            Message m = queue.poll();
            if (m != null) {
                System.out.println("Consumer: " + m.toString());
            }
        }
    }
}

Message.java


/*
 * Copyright 2011 Blue Lotus Software, LLC.
 * Copyright 2011 John Yeary
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * $Id: Message.java 347 2011-05-23 12:22:29Z jyeary $
 */
package com.bluelotussoftware.thread.example;

/**
 *
 * @author John Yeary
 * @version 1.0
 */
public class Message {

    private int id;
    private String message;

    public Message(int id, String message) {
        this.id = id;
        this.message = message;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    @Override
    public String toString() {
        return "Message{ id:" + id + ",message: " + message + "}";
    }
}


Enhanced by Zemanta

Tuesday, May 10, 2011

JSF 2.1.x on Tomcat 6.0

Why does it need to be so difficult to find the right combinations of voodoo to make enterprise applications work? I don't really want an answer. It is just a rhetorical question.

Cay Horstmann has a really good blog entry on JSF 2.0 and Tomcat. It is from a couple of years ago though.

I thought that I would add a little more information to well of knowledge. I have JSF 2.1.1-b04 running on Tomcat 6.0.32 with the addition of new EL (Expression Language) libraries and a context parameter to the web.xml

pom.xml

        <dependency>
            <groupId>javax.el</groupId>
            <artifactId>el-api</artifactId>
            <version>2.2.1-b04</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.web</groupId>
            <artifactId>el-impl</artifactId>
            <version>2.2.1-b05</version>
        </dependency>

web.xml

    <context-param>
        <param-name>com.sun.faces.expressionFactory</param-name>
        <param-value>com.sun.el.ExpressionFactoryImpl</param-value>
    </context-param>

These minor additions allow you to take full advantage of JSF 2.1.x EL syntax. This includes the capability to include parameters to your EL methods such as the action in the h:commandButton below:

        <h:form id="form1">
            <h:inputText id="inputText1" value="#{indexBean.message}"/>
            <h:commandButton id="commandButton1" type="submit" value="Submit" 
                             action="#{indexBean.someAction(value)}"/>
        </h:form>

Monday, May 02, 2011

JCP Elections 26 April - 09 May 2011

Java Community ProcessImage by Obie Fernandez via Flickr
The JCP is holding elections for the open Executive Committee seats. This includes ratified seats, and openly elected seats. If you are a JCP member, or would like to vote (you must join JCP to vote), please do so. It is so important for the community to make sure that it is adequately represented. In order for the JCP to function, we need dedicated individuals who can rise above the current tumult, and deliver a positive message. We need focus to be on the Java Community Process, and not on political infighting.

As a JCP member, I have cast my ballot. Have you?

Oracle's nominations for the two open ratified seats on the SE/EE Executive Committee are:
  • The Brazilian Java User Group SouJava, represented by Bruno Souza
  • Goldman Sachs, represented by John Weir
The nominees for the open elected seats on the Executive Committee are:
  • Alex Terrazas - ME
  • Central Ohio Java Users Group - SE/EE
  • George Gastaldi - SE/EE
  • Siddique Hameed - SE/EE
  • Liferay, Inc. - SE/EE
  • London Java Community - SE/EE

I would like to encourage all voting members to ratify Bruno Souza (Representing SouJava). Bruno has been the face of the Java community for many years. He is internationally recognized, and truly represents the heart of the Java community.

The other elected seats include two Java Users Groups: Central Ohio Users Group and London Java Community. I would encourage all voting members to vote for the Java User Groups (JUG) community membership. These groups represent the diversity of the JUG community, and have community interests rather than corporate interests at their heart.

Dan Sline represents the Central Ohio Users Group and I would encourage JCP members to consider him. Otherwise, please consider voting for the London Java Community. It is vitally important to support the communities that are here to serve you.
Enhanced by Zemanta

Popular Posts