Pages

Saturday, November 27, 2010

Dynamic JSF 2.0 Page

I have had a number of folks ask about templates and JSF. There seems to be a misconception that you need a template for all of your content, and that the content can not be dynamically generated for a page. This is not true! I am not sure where this comes from, but it is not uncommon question.

Dynamic JSF Page

The example NetBeans project in the link below, demonstrates how to to use the binding attribute to inject the required information into a page before rendering it. I have added the binding attribute to the <body> tag. This allows me to modify the content of the page body before it is rendered.

I have also included how to use the ValueExpression to set the value of the rendered text. This example should be sufficient to demonstrate the capabilities.

The project code is a NetBeans project: DynamicJSF.zip

Thursday, November 25, 2010

Oracle Certified Java Programmer Boot Camp Code Examples

Java Mascot introducing Netbeans.Image via Wikipedia
I uploaded all of my code examples today for the free Oracle™ Certified Java™ Programmer Boot Camp that I do for the Greenville Java Users Group (GreenJUG).

You can find more information on the JUG site about the boot camp, and from the links below. The projects are NetBeans 6 files.

You need to still need to attend for the presentations! If I posted those, you wouldn't feel the need to come and participate.

Code Examples

Links



Enhanced by Zemanta

Wednesday, November 24, 2010

Creating Charts on Headless Systems: JFreechart and Rogue Wave

JFreechart Example
This week we had an interesting conundrum at work. We had a headless server which is not uncommon, that would not generate charts in our web based application. Apparently some of the charts are not used very often, or it would have been reported sooner. The charts in question were originally created using Rogue Wave Software charting software from 1999-2000. This software was used to create charts in AWT based applications. Yes, I said AWT not Swing, and I know that it is very old.

The particular charts do not have replacements available in free charting software like JFreechart currently, and are available only as commercial software. We had purchased the original software and licenses from Rogue Wave, and did not want to purchase new commercial software.

Now to the conundrum. Since Java 1.4, heavyweight AWT and Swing components throw a HeadlessException, if you attempt to run them on a headless system.

As you can see from the list, it does not leave much room for the developer to work with in a headless environment. Fair enough, AWT/Swing are GUI environments.

The graphical libraries used to create charts in the case of Rogue Wave and JFreechart generally expect a GUI framework. Rogue Wave is expecting to generate the chart images in a Window, or one of its subclasses like Frame. This can cause an issue as you can see. So I am left with a couple of components that I can use like Component, Canvas, and Panel.

You can create a headless environment and check it with the code below.

System.setProperty("java.awt.headless", "true");
boolean headless = GraphicsEnvironment.isHeadless();
System.out.println("Headless: " + headless);

So how do you generate the charts, or create images in general on a headless system. It turns out to be quite simple. Since all components have a paint(Graphics g) method, and JFreechart has a createBufferedImage() method. These turn out to be the keys.

Solution

We need to create a BufferedImage which we can pass to the Component to paint. Once we create the image to paint to, we simply ask the component to paint it, and use ImageIO to output our chart.

Note: You will need to have the Rogue Wave graphing and gif libraries, or you may comment out those code sections.

NetBeans 6.9 project files: HeadlessAWT.zip

Headless.java

/*
 *  Copyright 2010 Blue Lotus Software.
 *  Copyright 2010 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.
 *  under the License.
 */
package com.bluelotussoftware.graph.headless.example;

import java.awt.*;
import java.io.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.util.Locale;
import com.roguewave.chart.awt.datamodels.v2_2.SampleData;
import com.roguewave.chart.awt.standard.v2_2.beans.PieChart;
import com.roguewave.chart.awt.standard.v2_2.beans.LineChart;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.encoders.ImageFormat;
import org.jfree.data.general.DefaultKeyedValuesDataset;
import org.jfree.data.general.DefaultPieDataset;

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

    private static BufferedImage generateRectangle(Component component, int width, int height) {
        BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics graphics = bufferedImage.getGraphics();
        graphics.setColor(Color.WHITE);
        graphics.fillRect(0, 0, width, height);
        graphics.setColor(Color.ORANGE);
        graphics.fill3DRect(50, 50, 300, 300, true);
        component.paint(graphics);
        return bufferedImage;
    }

    private static BufferedImage generateRectangle(Component component) {
        return generateRectangle(component, 400, 400);
    }

    private static BufferedImage generateCylinder(int width, int height) {
        Panel panel = new Panel();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics graphics = image.getGraphics();
        graphics.setColor(Color.WHITE);
        graphics.fillRect(0, 0, width, height);
        graphics.setColor(Color.ORANGE);
        graphics.drawOval(100, 100, 50, 75);
        graphics.fillOval(200, 100, 50, 75);
        graphics.drawLine(125, 100, 225, 100);
        graphics.drawLine(125, 175, 225, 175);
        panel.paint(graphics);
        return image;
    }

    private static boolean save(BufferedImage image, Component component) {
        boolean success = false;
        try {
            ImageIO.write(image, "gif", new FileOutputStream(component.getClass().getSimpleName() + ".gif"));
            success = true;
        } catch (FileNotFoundException fnfe) {
            fnfe.printStackTrace(System.err);
        } catch (IOException ex) {
            ex.printStackTrace(System.err);
        }
        return success;
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws IOException {
        System.setProperty("java.awt.headless", "true");
        boolean headless = GraphicsEnvironment.isHeadless();
        System.out.println("Headless: " + headless);
        Toolkit tk = Toolkit.getDefaultToolkit();
        tk.beep();

        BufferedImage bufferedImage = null;
        boolean success = false;

        // ---------------------------------------------------------------------------------------------- //
        Component component = new Component() {

            private static final long serialVersionUID = 3109256773218160485L;
        };
        Canvas canvas = new Canvas();
        Panel panel = new Panel();
        // ---------------------------------------------------------------------------------------------- //

        // Drawing Examples
        bufferedImage = Headless.generateRectangle(component);
        success = Headless.save(bufferedImage, component);
        System.out.println("Created " + component.getClass().getSimpleName() + " : " + success);
        success = false;

        bufferedImage = Headless.generateRectangle(canvas);
        success = Headless.save(bufferedImage, canvas);
        System.out.println("Created " + canvas.getClass().getSimpleName() + " : " + success);
        success = false;

//        bufferedImage = Headless.generateRectangle(panel);
//        success = Headless.save(bufferedImage, panel);
//        System.out.println("Created " + panel.getClass().getSimpleName() + " : " + success);
//        success = false;

        bufferedImage = Headless.generateCylinder(400, 400);
        success = Headless.save(bufferedImage, panel);
        System.out.println("Created " + panel.getClass().getSimpleName() + " : " + success);
        success = false;
        // ---------------------------------------------------------------------------------------------- //

        // Rogue Wave Examples
        SampleData sd = new SampleData();
        LineChart lineChart = new LineChart();
        lineChart.setData(sd);
        PieChart pieChart = new PieChart();
        pieChart.setData(sd);

        // The chart size is required.
        lineChart.setSize(400, 400);
        pieChart.setSize(400, 400);

        bufferedImage = new BufferedImage(400, 400, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = (Graphics2D) bufferedImage.getGraphics();
        lineChart.paint(g);
        ImageIO.write(bufferedImage, ImageFormat.PNG, new FileOutputStream("LineChart.png"));
        pieChart.paint(g);
        ImageIO.write(bufferedImage, ImageFormat.PNG, new FileOutputStream("PieChart.png"));
        // ---------------------------------------------------------------------------------------------- //

        // JFreechart Examples
        DefaultPieDataset dpds = new DefaultKeyedValuesDataset();
        dpds.setValue("Java", 60.0);
        dpds.setValue("C++", 20.0);
        dpds.setValue("MS Technologies", 10.0);
        dpds.setValue("Misc.", 10.0);

        JFreeChart jfc = ChartFactory.createPieChart("Programming Languages", dpds, true, true, Locale.ENGLISH);
        bufferedImage = jfc.createBufferedImage(400, 400);
        ImageIO.write(bufferedImage, "gif", new FileOutputStream("jfc-piechart.gif"));
    }
}

Enhanced by Zemanta

Saturday, November 06, 2010

JDK 7: The wait is over in OpenJDK

I did a presentation last month for our Greenville Java Users Group about the proposed features set for JDK 7. My claim is that they are already here in OpenJDK. Granted there still needs to be some fine tuning, but all of the proposed features will work.
You may need to turn on some JVM parameters to make them work, but they work.


JSR 292: Support for dynamically-typed languages (InvokeDynamic)

The following parameters need to be passed to the JVM:

-XX:+UnlockExperimentalVMOptions \
-XX:+EnableInvokeDynamic


An example of how this is implemented can be found at:

Support for Dynamically Typed Languages in the Java Virtual Machine

JSR TBD: Small language enhancements (Project Coin)

The simplified enhancements to improve developer productivity include:
  • Underscore separators for integral literals (primitive types).
  • "Diamond Operator" for simplified generic instance creation.
  • Strings in switch statements.

JSR 166y: Concurrency and Collections Updates

The best known reference is to ForkJoin operations from JavaOne, but it includes so much more. A great example of a Fork-Join operation can be found at: JSR-166: The Java fork/join Framework.

JSR 203: More new I/O APIs for the Java platform (NIO.2)

In the example at the bottom of the blog, I show the Path class. This includes some additional functionality where we expect "Files" and "Directories (path)" information to be separate.

A really cool new feature is the WatcherService API. This allows us to watch a file, or directory for changes. A great example can be found here: WatchDir.java.

This is just a few examples of the great things that are available in OpenJDK today. So if you want to try out the new features, download a binary distribution for your platform, or better still: download the source and build it yourself.

As promised here is my example code which demonstrates some of the features. You will need to download the ParallelMergeSort from the Fork-Join framework link above to compile it. Also if you are using NetBeans, it has a number of hooks already in place for OpenJDK (JDK 7/8).

Example.java

/*
 *  Copyright 2010 Blue Lotus Software, LLC.
 *  Copyright 2010 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.
 *  under the License.
 */
/*
 * $Id: Example.java 304 2010-11-06 16:32:05Z jyeary $
 */
package com.bluelotussoftware.example.jdk7;

import java.io.File;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.Arrays;

public class Example {

    public static void main(String... args) {

        Map<String, String> map = new HashMap<>();
        map.put("Hello", "World");
        System.out.println(map.get("Hello"));

        Map<String, Map<String, String>> multimap = new HashMap<>();
        Map<String, String> enclosed = new HashMap<>();
        enclosed.put("name", "value");
        multimap.put("map1", map);
        multimap.put("map2", enclosed);

        System.out.println(multimap.get("map2").get("name"));


        int x = 0b0_1;
        int y = 0b1000_0100_0010_0001;
        int z = 123___456___789___0;

        System.out.println(x);
        System.out.println(y);
        System.out.println(z);

        String testCase = "openJDK";

        switch (testCase) {
            case "yummy": {
                System.out.println("Yummy");
                break;
            }
            case "meloncholy": {
                System.out.println("Sad");
                break;
            }
            case "openJDK": {
                System.out.print("The future of Java...");
            }
            case "jdk7":
                System.out.print(" today.\n");
        }

        File f = new File(System.getProperty("user.home"));
        Path p = f.toPath();
        System.out.println("Current Path: " + p.toString());

        Integer[] assorted = new Integer[5000];
        Random generator = new Random();

        for (int i = 0; i < 5000; i++) {
            assorted[i] = generator.nextInt(1_000_000);
        }
        System.out.println("\n\n\n\n\nunsorted: " + Arrays.toString(assorted) + "\n\n\n\n\n");

        ParallelMergeSort.sort(assorted);

        System.out.println("sorted: " + Arrays.toString(assorted));

    }
}
Enhanced by Zemanta

Apache Maven AntRun Plugin Configuration

Apache Maven logo.Image via Wikipedia
I was looking for an up-to-date example of how to use the Apache Maven AntRun plugin version 1.6. The examples that I found on the plugin's home page have not kept pace with the actual development.

I have included my build.xml example file below, and the pom.xml configuration to run it. Please note the comments under the antrun plugin to understand what is happening.

build.xml

<?xml version="1.0" encoding="UTF-8"?>
<project name="mavenproject1" default="default" basedir=".">
    <target name="default">
        <echo message="Hello World from build.xml"/>
    </target>
</project>
pom.xml

<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>com.bluelotussoftware.example.jsf</groupId>
    <artifactId>mavenproject1</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>mavenproject1</name>
    <url>http://maven.apache.org</url>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.0.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-antrun-plugin</artifactId>
                <version>1.6</version>
                <executions>
                    <execution>
                        <phase>compile</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <target>
                                <!-- Execute an ant task within maven -->
                                <echo message="Hello World from pom.xml"/>
                                <!-- Execute an ant task in an external build.xml file. It assumes the file is called 
                                build.xml and is located in the same directory as the pom.xml file. The target in
                                the external file is called default.
                                -->
                                <ant target="default"/>
                            </target>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
</project>
Enhanced by Zemanta