Wednesday, August 28, 2013

Running Maven war packaging project without pom config

Use Jetty (latest 9.x requires JDK7)

bash> mvn org.eclipse.jetty:jetty-maven-plugin:run -Djetty.port=8081

Or use Jetty on JDK 6

bash> mvn org.mortbay.jetty:jetty-maven-plugin:8.1.12.v20130726:run -Djetty.port=8081

Or use Tomcat

bash> mvn org.apache.tomcat.maven:tomcat7-maven-plugin:run -Dmaven.tomcat.port=8081

Monday, August 26, 2013

How to create web-app with Quartz Scheduler and logging

I sometimes help out users in Quartz Scheduler forums. Once in a while some one would ask how can he/she setup the Quartz inside a web application. This is actualy a fairly simple thing to do. The library already comes with a ServletContextListener that you can use to start a Scheduler. I will show you a simple webapp example here.

First create a Maven pom.xml file.

<?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">

    <modelVersion>4.0.0</modelVersion>

    <groupId>quartz-web-demo</groupId>
    <artifactId>quartz-web-demo</artifactId>
    <packaging>war</packaging>
    <version>1.0-SANPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.2.0</version>
        </dependency>
    </dependencies>

</project>

Then you need to create a src/main/webapp/META-INF/web.xml file.

<?xml version="1.0" encoding="UTF-8"?>
 <web-app version="2.5"
    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/web-app_2_5.xsd">

     <context-param>
         <param-name>quartz:config-file</param-name>
         <param-value>quartz.properties</param-value>
     </context-param>
     <context-param>
         <param-name>quartz:shutdown-on-unload</param-name>
         <param-value>true</param-value>
     </context-param>
     <context-param>
         <param-name>quartz:wait-on-shutdown</param-name>
         <param-value>true</param-value>
     </context-param>
     <context-param>
         <param-name>quartz:start-on-load</param-name>
         <param-value>true</param-value>
     </context-param>

     <listener>
         <listener-class>org.quartz.ee.servlet.QuartzInitializerListener</listener-class>
     </listener>

 </web-app>

And lastly, you need a src/main/resources/quartz.properties config file for Scheduler.

# Main Quartz configuration
org.quartz.scheduler.skipUpdateCheck = true
org.quartz.scheduler.instanceName = MyQuartzScheduler
org.quartz.scheduler.jobFactory.class = org.quartz.simpl.SimpleJobFactory
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 5

You may configure many other things with Quartz, but above should get you started as in In-Memory scheduler.

Now you should able to compile and run it.

bash> mvn compile
bash> mvn org.apache.tomcat.maven:tomcat7-maven-plugin:2.1:run -Dmaven.tomcat.port=8081

How to configure logging for Quartz Scheduler

Another frequently asked question is how do they setup logging and see the DEBUG level messages. The Quartz Schedulers uses SLF4J, so you have many loggers options to choose. I will show you how to setup Log4j for example below.

First, add this to your pom.xml

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.5</version>
        </dependency>

Then add src/main/resources/log4j.properties file to show messages onto STDOUT.

log4j.rootLogger=INFO, stdout
log4j.logger.org.quartz=DEBUG
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n

Restart your web application on command line, and now you should see all the DEBUG level logging messages coming from Quartz library.

With everything running, your next question might be asking how do you access the scheduler from your web application? Well, when the scheduler is created by the servlet context listener, it is stored inside the web app’s ServletContext space with org.quartz.impl.StdSchedulerFactory.KEY key. So you may retrieve it and use it in your own Servlet like this:

public class YourServlet extends HttpServlet {
    public init(ServletConfig cfg) {
        String key = "org.quartz.impl.StdSchedulerFactory.KEY";
        ServletContext servletContext = cfg.getServletContext();
        StdSchedulerFactory factory = (StdSchedulerFactory) servletContext.getAttribute(key);
        Scheduler quartzScheduler = factory.getScheduler("MyQuartzScheduler");
        // TODO use quartzScheduler here.
    }
}

Now you are on your way to build your next scheduling application!

Have fun!

Saturday, August 24, 2013

MySchedule-3.2.1.0 is out!

The main work on this release is upgrade to Quartz 2.2.1

- Upgraded to Quartz 2.2.1
- Upgraded to SLF4J 1.7.5

- Quartz 2.2.1 API has some changes that break backward compatibility and this release addressed these
  issues:

  -- SchedulerPlugin interface now has different #initialize() signature
  -- SchedulerListener interface has added new method #schedulerStarting()
  -- Scheduler interface has couple new methods addJobs and schedulerJobs with Set instead of List.

Get it here: https://code.google.com/p/myschedule/downloads/list

Wednesday, August 21, 2013

Getting started with Apache Camel using Java

Apache Camel is a very useful library that helps you process events or messages from many different sources. You may move these messages through many different protocols such as between VM, HTTP, FTP, JMS, or even DIRECTORY/FILE, and yet still keep your processing code free of transport logic. This allows you to concentrate on digesting the content of the messages instead.

Here I will provide a tutorial on how you can get started with Apache Camel using Java.

Let’s start by creating a Maven project pom.xml file first.

<?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">

    <modelVersion>4.0.0</modelVersion>
    <groupId>camel-spring-demo</groupId>
    <artifactId>camel-spring-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <camel.version>2.11.1</camel.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-core</artifactId>
            <version>${camel.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.5</version>
        </dependency>
    </dependencies>

</project>

We are only going to explore the camel-core, which actually contains quite of few useful components that you may use. Also for logging purpose, I have added a slf4j-simple as a logger implementation so we may see output on console.

Next you just need a class to construct an Route. A Route is like a instruction definition to Camel on how to move your messages from one point to another. We are going to create src/main/java/camelcoredemo/TimerRouteBuilder.java file that will generate a timer message on every second, and then pass to a processor that simply logs it.

package camelcoredemo;

import org.slf4j.*;
import org.apache.camel.*;
import org.apache.camel.builder.*;

public class TimerRouteBuilder extends RouteBuilder {
    static Logger LOG = LoggerFactory.getLogger(TimerRouteBuilder.class);
    public void configure() {
        from("timer://timer1?period=1000")
        .process(new Processor() {
            public void process(Exchange msg) {
                LOG.info("Processing {}", msg);
            }
        });
    }
}

That’s all you needed to get started. Now you may build and run this simple demo.

bash> mvn compile
bash> mvn exec:java -Dexec.mainClass=org.apache.camel.main.Main -Dexec.args='-r camelcoredemo.TimerRouteBuilder'

Notice that we didn’t even write a Java main class, but simply use the org.apache.camel.main.Main option to accepts a RouteBuilder class name as parameter. Then it will load and create the route automatically.

Controlling the CamelContext

When you start Camel, it creates a CamelContext object that holds many information on how to run it, including the definition of the Route we created. Now if you want to have more control over this CamelContext, then you would need to write your own Main class. I will show you a simple one here.

package camelcoredemo;

import org.slf4j.*;
import org.apache.camel.*;
import org.apache.camel.impl.*;
import org.apache.camel.builder.*;

public class TimerMain {
    static Logger LOG = LoggerFactory.getLogger(TimerMain.class);
    public static void main(String[] args) throws Exception {
        new TimerMain().run();
    }
    void run() throws Exception {
        final CamelContext camelContext = new DefaultCamelContext();
        camelContext.addRoutes(createRouteBuilder());
        camelContext.setTracing(true);
        camelContext.start();

        Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() {
                try {
                    camelContext.stop();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        });

        waitForStop();
    }
    RouteBuilder createRouteBuilder() {
        return new TimerRouteBuilder();
    }
    void waitForStop() {
        while (true) {
            try {
                Thread.sleep(Long.MAX_VALUE);
            } catch (InterruptedException e) {
                break;
            }
        }
    }
}

As you can see, we re-used the existing TimerRouteBuilder class inside createRouteBuilder() method. Our Main class now have full control when to create, start and stop the CamelContext. This context allow you to have control on how to configure Camel globally rather than on Route level. The javadoc link gives all the setter methods that you can explore on what it can do.

Noticed that we also need to provide few setup codes in our Main class. First we need to handle graceful shutdown, so we added a Java shutdown hook to invoke the context stop(). Secondly we need to add a thread block after context has started. The reason for this is that the CamelContext#start() method is non-blocking! If you don’t block your Main thread after start, then it will simply exit right after it, which will have not much use. You want to run Camel as a service (like a server) until you explicitly press CTRL+C to terminate the process.

Improving the Main class to start CamelContext

If you don’t want to deal with much of the Main class setup code such as above, then you may simply extends the org.apache.camel.main.Main class provided by camel-core intead. By piggy-back on this class, you will only not have your Context auto setup, but you will get all the additional command line features such as controlling how long to run the process for, enabling tracing, loading custom route class etc.

Refactoring previous example, here is how it look like.

package camelcoredemo;

import org.slf4j.*;
import org.apache.camel.builder.*;
import org.apache.camel.main.Main;

public class TimerMain2 extends Main {
    static Logger LOG = LoggerFactory.getLogger(TimerMain2.class);
    public static void main(String[] args) throws Exception {
        TimerMain2 main = new TimerMain2();
        main.enableHangupSupport();
        main.addRouteBuilder(createRouteBuilder());
        main.run(args);
    }
    static RouteBuilder createRouteBuilder() {
        return new TimerRouteBuilder();
    }
}

Now our TimerMain2 is much shorter, and you may try it out and it should function the same as before.

bash> mvn compile
bash> mvn exec:java -Dexec.mainClass=camelcoredemo.TimerMain2 -Dexec.args='-t'

Notice that we have given -t option and it will dump Route tracing. Use -h and you will see all the available options.

Adding bean to the Camel Registry

In the TimerRouteBuilder example above, we have created a Processor on the fly. Now if you were to combine few different Processor together, it would be nicer to minimize the noise. Camel allow you to do this by registering processing beans in their registry space, and then you simply reference them in your route as bean component. Here is how I can convert above example into beans processing.

package camelcoredemo;

import org.slf4j.*;
import org.apache.camel.*;
import org.apache.camel.builder.*;
import org.apache.camel.main.Main;

public class TimerBeansMain extends Main {
    static Logger LOG = LoggerFactory.getLogger(TimerBeansMain.class);
    public static void main(String[] args) throws Exception {
        TimerBeansMain main = new TimerBeansMain();
        main.enableHangupSupport();
        main.bind("processByBean1", new Bean1());
        main.bind("processAgainByBean2", new Bean2());
        main.addRouteBuilder(createRouteBuilder());
        main.run(args);
    }
    static RouteBuilder createRouteBuilder() {
        return new RouteBuilder() {
                public void configure() {
                    from("timer://timer1?period=1000")
                    .to("bean:processByBean1")
                    .to("bean:processAgainByBean2");
                }
            };
    }

    // Processor beans
    static class Bean1 implements Processor {
        public void process(Exchange msg) {
            LOG.info("First process {}", msg);
        }
    }
    static class Bean2 implements Processor {
        public void process(Exchange msg) {
            LOG.info("Second process {}", msg);
        }
    }
}

Now you see my Route is very slim and without noise clutter; and I have refactored my processing code into individual classes. This promotes better code management and testing as you write more complex Route to address business logic. It let you build LEGO like block of re-usable POJO beans. Besides just processing beans, Camel use this registry space for many other services as well. For example you may customize many other component endpoints with additional features and or configurations. Or thing such as thread pool strategy implementation replacement etc.

The Route in example above is constructed using what’s called Java DSL. The route is very readable, and yet you’ll get full IDE support to browse all the methods available to use for your route.

I hope this article has helped you jump start your Camel ride. Besides the timer component mentioned, the camel-core also comes with the following components out of it’s core jar.

Have fun!

Monday, August 19, 2013

How to configure SLF4J with different logger implementations

There are many good benefits in using slf4j library as your Java application logging API layer. Here I will show few examples on how to use and configure it with different loggers.
You can think of slf4j as an Java interface, and then you would need an implementation (ONLY ONE) at runtime to provide the actual logging details, such as writing to STDOUT or to a file etc. Each logging implementation (or called binding) would obviously have their own way of configuring the log output, but your application will remain agnostic and always use the same org.slf4j.Logger API. Let’s see how this works in practice.

Using slf4j with Simple logger

Create a Maven based project and this in your pom.xml.
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.5</version>
    </dependency>
Now you may use Logger in your Java code like this.
package deng;
import org.slf4j.*;
public class Hello {
    static Logger LOGGER = LoggerFactory.getLogger(Hello.class);
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++)
            if (i % 2 == 0)
                LOGGER.info("Hello {}", i);
            else
                LOGGER.debug("I am on index {}", i);
    }
}
The above will get your program compiled, but when you run it, you will see these output.
bash> java deng.Hello
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
What it’s saying is that at runtime, you are missing the logging "implementation" (or the logger binding), so slf4j simply use a "NOP" implmentation, which does nothing. In order to see the output properly, you may try use an simple implementation that does not require any configuration at all! Just go back to your pom.xml and add the following:
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-simple</artifactId>
        <version>1.7.5</version>
    </dependency>
Now you see logging output on STDOUT with INFO level. This simple logger will default show any INFO level message or higher. In order to see DEBUG messages, you would need to pass in this System Property -Dorg.slf4j.simpleLogger.defaultLogLevel=DEBUG at your Java startup.

Using slf4j with Log4j logger

Now we can experiment and swap different logger implementations, but your application code can remain the same. All we need is to replace slf4j-simple with another popular logger implementation, such as the Log4j.
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.5</version>
    </dependency>
Again, we must configure logging per implementation that we picked. In this case, we need an src/main/resources/log4j.properties file.
    log4j.rootLogger=DEBUG, STDOUT
    log4j.logger.deng=INFO
    log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender
    log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout
    log4j.appender.STDOUT.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n
Re-run your program, and you should see similar output.

Using slf4j with JDK logger

The JDK actually comes with a logger package, and you can replace pom.xml with this logger implementation.
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-jdk14</artifactId>
        <version>1.7.5</version>
    </dependency>
Now the configuration for JDK logging is a bit difficult to work with. Not only need a config file, such as src/main/resources/logging.properties, but you would also need to add a System properties -Djava.util.logging.config.file=logging.properties in order to have it pick it up. Here is an example to get you started:

.level=INFO
handlers=java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level=FINEST
deng.level=FINEST

Using slf4j with Logback logger

The logback logger implementation is a super dupa quality implementation. If you intend to write serious code that go into production, you may want to evaluate this option. Again modify your pom.xml to replace with this:
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.0.13</version>
    </dependency>
Here is a sample of configuration src/main/resources/logback.xml to get things started.
<configuration>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  </appender>

  <logger name="deng" level="DEBUG"/>

  <root level="INFO">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

Writing your own library with slf4j logger

If you are providing an Java library for large end users consumption, it’s good idea to set your project to depend on slf4j-api only, and then let your user choose any logger implementation at their development or runtime environment. As end users, they may quickly select one of option above and take advatage of their own favorite logging implementation features.

Sunday, August 18, 2013

How to convert asciidoc text to html using Groovy

Here is how you can convert asciidoc text using Groovy script:

// filename: RunAsciidoc.groovy
@Grab('org.asciidoctor:asciidoctor-java-integration:0.1.3')
import org.asciidoctor.*
def asciidoctor = Asciidoctor.Factory.create()
def output = asciidoctor.renderFile(new File(args[0]),  [:])
println(output);

Now you may run it

groovy RunAsciidoc.groovy myarticle.txt

Many thanks to the asciidoctor.org project!