RSS

Category Archives: Java Pro

Reporting with Eclipse BIRT and Java Objects (POJO’s) – Tutorial

Tutorial

by Lars Vogel

Reporting with Eclipse BIRT and Java Objects (POJO’s) – Tutorial

Lars Vogel Hendrik Still

Version 1.2

Copyright © 2008 – 2011 Lars Vogel

26.06.2011

Revision History
Revision 0.1 – 0.2 07.03.2008 Hendrik Still, Lars Vogel
Created Article
Revision 0.3 – 1.2 07.03.2009 – 26.06.2011 Lars
Vogel
bug fixes and enhancements
Eclipse BirtThis tutorial describes how to use Eclipse BIRT for reporting on simple Java Objects (POJO’s). The tutorial explains also how to deploy the resulting BIRT report into a webcontainer (Tomcat) and how to use it in an Eclipse RCP application. Eclipse 3.7 (Indigo) is used for this tutorial.

1. Eclipse BIRT

1.1. Overview

Eclipse BIRT allows the creation of reports based on data from different data sources. Data sources define where the data is stored.

BIRT provides for example the following data sources:

  • Databases (via JDBC)
  • Text Files (cvs, XML)
  • WebServices (via WSDL-Files)
  • Scripting Data sources

You use in BIRT “Data sets” to defines queries on data source. These data sets can be used in a report.

In a Java program it is often convenient to use Java objects as a data source for reports. This article will focus on the usage of plain old Java objects (POJO) as data sources for BIRT reports.

1.2. Example

In this tutorial we will build a report which will show us information about the stock market. We get the information from a Java Object. The data will be displayed in a chart and in a table with detailed information. The result should look like this:

2. Installation

Use the Eclipse Update Manager to install “Business Intelligence, Reporting and Charting” -> BIRT Framework.

3. Create Project and REport

Create a new Java Project with the name “de.vogella.birt.stocks”.

Create a new report “stock_report.rptdesign” via File -> New -> Other -> Business Intelligence and Reporting -> Report.

The new report is displayed in the “Report Design” perspective. Delete everything in the example report except the report header. The result should look like the following.

4. Java classes

The report will display stock data. To demonstrate BIRT we use a Mock object for providing the data.

Create package “de.vogella.birt.stocks.model” and then the following class. This class will represent the domain model.

package de.vogella.birt.stocks.model;

import java.util.Date;
/** * Domain model for stock data * @author Lars Vogel */
public class StockData {
	private Date date;
	private double open;
	private double high;
	private double low;
	private double close;
	private long volume;

	public double getClose() {
		return close;
	}

	public void setClose(double close) {
		this.close = close;
	}

	public Date getDate() {
		return date;
	}

	public void setDate(Date date) {
		this.date = date;
	}

	public double getHigh() {
		return high;
	}

	public void setHigh(double high) {
		this.high = high;
	}

	public double getLow() {
		return low;
	}

	public void setLow(double low) {
		this.low = low;
	}

	public double getOpen() {
		return open;
	}

	public void setOpen(double open) {
		this.open = open;
	}

	public long getVolume() {
		return volume;
	}

	public void setVolume(long volume) {
		this.volume = volume;
	}

}

Create the package “de.vogella.birt.stocks.daomock” and then the following class “StockDaoMock”. This will only mock / fake the data and not really get it from the Internet. As we want to learn BIRT here this should be fine.

package de.vogella.birt.stocks.daomock;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import de.vogella.birt.stocks.model.StockData;

public class StockDaoMock {

	public List<StockData> getStockValues(String company) {
		// Ignore the company and always return the data
		// A real implementation would of course use the company string
		List<StockData> history = new ArrayList<StockData>();
		// We fake the values, we will return fake value for 01.01.2009 -
		// 31.01.2009
		double begin = 2.5;
		for (int i = 1; i <= 31; i++) {
			Calendar day = Calendar.getInstance();
			day.set(Calendar.HOUR, 0);
			day.set(Calendar.MINUTE, 0);
			day.set(Calendar.SECOND, 0);
			day.set(Calendar.MILLISECOND, 0);
			day.set(Calendar.YEAR, 2009);
			day.set(Calendar.MONTH, 0);
			day.set(Calendar.DAY_OF_MONTH, i);
			StockData data = new StockData();
			data.setOpen(begin);
			double close = Math.round(begin + Math.random() * begin * 0.1);
			data.setClose(close);
			data.setLow(Math.round(Math.min(begin, begin - Math.random() * begin * 0.1)));
			data.setHigh(Math.round(Math.max(begin, close) + Math.random() * 2));
			data.setVolume(1000 + (int) (Math.random() * 500));
			begin = close;
			data.setDate(day.getTime());
			history.add(data);
		}
		return history;
	}
}

5. Datasource and Dataset

To use Java Objects (POJO’s) as datasource in Eclipse BIRT you have to map the fields of your Java classes to JavaScript. This JavaScript is used in your report and will access the Java Object.

5.1. Create Data Source

The data source connects your data with your report. BIRT provides different types of data sources, we use the “Scripted Data Source”. Go back to your stocks_report, use the “Report Design” perspective and select the “Data Explorer” View.

Tip

You have to select your report to display the content of the datasource view.

Create a new datasource, named “srcStocks” in your report.

5.2. The Dataset

The dataset defines the mapping for the datasource data and the BIRT data. Create a new dataset named “dataSetSocks”.

Press next and define the columns for your report.

5.3. JavaScript

Now we have to write the JavaScript for our dataset. Select the dataset and choose “open” as script. The open script is called before the first access to the dataset. We use this to load our List with the stock objects. To access a Java class you only have to use the following syntax: Packages.myJavaClass where myJavaClass is the full qualified Java class name.

Tip

In case you don’t see the script please node that the editor for the report has several tab. One of it is labeled “source”.

count = 0;

// Create instance of
// the GetStockHistory class
gsh = new Packages.de.vogella.birt.stocks.daomock.StockDaoMock(); 

//Load the List

stock = gsh.getStockValues("Java");

Place the following coding in the fetch script.

if(count < stock.size()){
       row["columnDate"] = stock.get(count).getDate();
       row["columnOpen"] = stock.get(count).getOpen();
       row["columnHigh"] = stock.get(count).getHigh();
       row["columnLow"] = stock.get(count).getLow();
       row["columnClose"] = stock.get(count).getClose();
       row["columnVolume"] = stock.get(count).getVolume();
       count++;
       return true;
}

return false;

Check if your Script works by doubleclicking on the dataset -> Preview Result.

6. Display the data in a table

6.1. Overview

We will now display the data in a table.

6.2. Create a table

Switch from “Data Explorer” to the “Palette”. Select the tab “Layout”.

Drag and drop the table element on the report.

Define the following settings for the table.

Change back to the “Data Explorer”. And drag and drop the dataset columns into the “Details row” of the table.

The result should look like the following.

Done. You can see a preview of the report if you click on the “Review” Tab. The result should look like the following:

7. Chart

7.1. Create a Chart

Switch back to the Palette, select a chart and drag and drop it on your report.

Choose the Line Chart with the standard settings.

Press Next and select your data set.

At the next step we have to assign the columns to the axis. We assign the date to the x axis and the open value to the y axis via drag and drop.

Define 5 series in total. Assign the columns to these series by dragging the column to the Sum sign.

Currently the x axis shows first the newest date. Reverse the x axis by you have to sort the data ascending. Press the highlighted button.

Go to the next tab and give titles to your columns. Hide the last one.

The display of the dates use a long format, we would like to change this. Perform the following and choose “short” as date type of the x axis

Change the display of the lines via the following.

Press finish to include your chart into your report.

8. Deploying in Tomcat

8.1. Overview

The following explains how to use BIRT reports in Tomcat. In general you have to:

  • Install the BIRT webviewer in Tomcat
  • Export your BIRT project into a .jar file
  • Move the .jar file to the birt-install-directory/WEB-INF/lib directory
  • Move the report design file into the root directory of birt in tomcat
  • Restart Tomcat

8.2. Install BIRT in Tomcat

We will use a standalone Tomcat 6.0 which we assume is already installed. See Apache Tomcat Tutorial for details.

You need the “Deployment components of BIRT” http://download.eclipse.org/birt/downloads/.

Copy the birt.war of this download into the Tomcat webappsfolder.

Tip

Currently you have to install org.eclipse.commons.logging separately into Tomcat. Download this lib from http://commons.apache.org/logging/ and put the jars into the lib folder of Tomcat.

The Birt example should be available under http://localhost:8080/birt/.If you see something like this, your Tomcat an your Web Viewer should work correct.

8.3. Install your BIRT reports in Tomcat

To run your own reports you have to copy the .rptdesign file in the root of the birt folder in Tomcat. To make your Java classes available export your project into a jar file.

After that the jar file has to be copied to the Tomcat webapps/birt/WEB-INF/lib/ directory. Restart the Tomcat and navigate to your report.

Your report should be found under http://localhost:8080/birt/frameset?__report=stock_report.rptdesign

Tip

If you want to export your report to PDF you also need the library iText from (http://prdownloads.sourceforge.net/itext/itext-1.3.jar ) . Copy the iText.jar in “/birt-viewer/WEB-INF/platform/plugins/com.lowagie.itext/lib”. Now restart the Tomcat.

9. Deploying in Eclipse RCP application

9.1. BIRT deploying to an RCP Application

We can use the Birtviewer also in a local RCP Application, it isn’t more than an browser view which shows a HTML Page generated by an integrated Webserver.

The following assumes that you are already familiar with Eclipse RCP development. See Eclipse RCP Tutorial in case you need an introduction.

Convert “de.vogella.birt.stocks” to a plugin project, via right mouse click -> Configure -> “Convert to plug-in project”.

Create an new plugin project “de.vogella.birt.stocks.rcp”. Select the template “RCP Application with a view”.

Add the following plugins as dependendies to “de.vogella.birt.stocks.rcp”.

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Rcp
Bundle-SymbolicName: de.vogella.birt.stocks.rcp; singleton:=true
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: de.vogella.birt.stocks.rcp.Activator
Require-Bundle: org.eclipse.ui,
 org.eclipse.core.runtime,
 org.eclipse.birt.report.viewer,
 org.eclipse.birt.report.engine.emitter.html,
 de.vogella.birt.stocks,
 org.eclipse.birt,
 org.eclipse.birt.chart.ui,
 org.eclipse.birt.chart.device.extension,
 org.eclipse.birt.chart.device.pdf,
 org.eclipse.birt.chart.device.svg,
 org.eclipse.birt.chart.device.swt,
 org.eclipse.birt.chart.engine.extension,
 org.eclipse.birt.chart.reportitem,
 org.eclipse.birt.chart.reportitem.ui,
 org.eclipse.birt.chart.ui.extension,
 org.eclipse.birt.core.script.function,
 org.eclipse.birt.report.engine.script.javascript
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.6

Copy your report to “stock_report_rcp.rptdesign” into this new project. Open this report and change the “open” JavaScript to the following.

count = 0;
/* * load and init data reader * import Platform from org.eclipse.core.runtime */
importPackage(Packages.org.eclipse.core.runtime);

/* load bundle with POJOs and data loading class */

myBundle = Platform.getBundle("de.vogella.birt.stocks");

/* load data reader class */
readerClass = myBundle.loadClass("de.vogella.birt.stocks.daomock.StockDaoMock");

/* create new instance of DataReader */
readerInstance = readerClass.newInstance();

/* read data */
stock = readerInstance.getStockValues("Java");

Use this code as View.java.

package de.vogella.birt.stocks.rcp;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import org.eclipse.birt.report.viewer.utilities.WebViewer;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;
import org.osgi.framework.Bundle;

public class View extends ViewPart {
	public static final String ID = "de.vogella.birt.stocks.rcp.view";

	public void createPartControl(Composite parent) {
		String path = "";
		try {
			Bundle bundle = Platform.getBundle("de.vogella.birt.stocks.rcp");
			URL url = FileLocator.find(bundle, new Path(
					"stock_report_rcp.rptdesign"), null);
			path = FileLocator.toFileURL(url).getPath();
		} catch (MalformedURLException me) {
			System.out.println("Fehler bei URL " + me.getStackTrace());
		} catch (IOException e) {
			e.printStackTrace();
		}

		Browser browser = new Browser(parent, SWT.NONE);
		// Use the filename of your reportWebViewer.display(path, WebViewer.HTML, browser, "frameset");
	}
/** * Passing the focus request to the viewer’s control. */
	public void setFocus() {
	}
}

10. Thank you

Please help me to support this article:

Flattr this  

11. Questions and Discussion

Before posting questions, please see the vogella FAQ. If you have questions or find an error in this article please use the www.vogella.de Google Group. I have created a short list how to create good questions which might also help you.

12. Links and Literature

12.1. Source Code

Source Code of Examples

12.2.  Eclipse BIRT resources

http://wiki.eclipse.org/index.php/BIRT_Project

Eclipse BIRT Wiki

12.3. vogella Resources

Eclipse RCP Training (German) Eclipse RCP Training with Lars Vogel

Android Tutorial Introduction to Android Programming

GWT Tutorial Program in Java and compile to JavaScript and HTML

Eclipse RCP Tutorial Create native applications in Java

JUnit Tutorial Test your application

Git Tutorial Put everything you have under distributed version control system

Referenced from: http://www.vogella.de/articles/EclipseBIRT/article.html

 
Leave a comment

Posted by on February 14, 2012 in Android, Birt Report, Eclipse, Java Pro

 

Generic Singleton Class for Java

class singleton<T> {
    private static final singleton<?> instance = new singleton<Object>();
    private singleton() {}
    T variable;  

    public static singleton<?> getInstance() {
        return instance;
    }
}   
void test() {
    singleton<String> singletonString = (singleton<String>)singleton.getInstance();
    String s = singletonString.variable;
    singleton<Integer> singletonInteger = (singleton<Integer>)singleton.getInstance();
    Integer i = singletonInteger.variable;
} 

Referenced by: http://www.coderanch.com/t/470696/java/java/Generic-Singleton-Class

 
Leave a comment

Posted by on October 15, 2011 in Java Pro

 

Java Reflection: Private Fields and Methods

By Jakob Jenkov

Despite the common belief it is actually possible to access private fields and methods of other classes via Java Reflection. It is not even that difficult. This can be very handy during unit testing. This text will show you how.

Note: This only works when running the code as a standalone Java application, like you do with unit tests and regular applications. If you try to do this inside a Java Applet, you will need to fiddle around with the SecurityManager. But, since that is not something you need to do very often, it is left out of this text so far.

Here is a list of the topics covered in this text:

  1. Accessing Private Fields
  2. Accessing Private Methods

Accessing Private Fields

To access a private field you will need to call the Class.getDeclaredField(String name) orClass.getDeclaredFields() method. The methods Class.getField(String name) andClass.getFields() methods only return public fields, so they won’t work. Here is a simple example of a class with a private field, and below that the code to access that field via Java Reflection:

public class PrivateObject {

  private String privateString = null;

  public PrivateObject(String privateString) {
    this.privateString = privateString;
  }
}

PrivateObject privateObject = new PrivateObject("The Private Value");

Field privateStringField = PrivateObject.class.
            getDeclaredField("privateString");

privateStringField.setAccessible(true);

String fieldValue = (String) privateStringField.get(privateObject);
System.out.println("fieldValue = " + fieldValue);

This code example will print out the text “fieldValue = The Private Value”, which is the value of the private field privateString of the PrivateObject instance created at the beginning of the code sample.

Notice the use of the method PrivateObject.class.getDeclaredField("privateString"). It is this method call that returns the private field. This method only returns fields declared in that particular class, not fields declared in any superclasses.

Notice the line in bold too. By calling Field.setAcessible(true) you turn off the access checks for this particular Field instance, for reflection only. Now you can access it even if it is private, protected or package scope, even if the caller is not part of those scopes. You still can’t access the field using normal code. The compiler won’t allow it.

Accessing Private Methods

To access a private method you will need to call the Class.getDeclaredMethod(String name, Class[] parameterTypes) or Class.getDeclaredMethods() method. The methodsClass.getMethod(String name, Class[] parameterTypes) and Class.getMethods()methods only return public methods, so they won’t work. Here is a simple example of a class with a private method, and below that the code to access that method via Java Reflection:

public class PrivateObject {

  private String privateString = null;

  public PrivateObject(String privateString) {
    this.privateString = privateString;
  }

  private String getPrivateString(){
    return this.privateString;
  }
}

PrivateObject privateObject = new PrivateObject("The Private Value");

Method privateStringMethod = PrivateObject.class.
        getDeclaredMethod("getPrivateString", null);

privateStringMethod.setAccessible(true);

String returnValue = (String)
        privateStringMethod.invoke(privateObject, null);

System.out.println("returnValue = " + returnValue);

This code example will print out the text “returnValue = The Private Value”, which is the value returned by the method getPrivateString() when invoked on the PrivateObject instance created at the beginning of the code sample.

Notice the use of the methodPrivateObject.class.getDeclaredMethod("privateString"). It is this method call that returns the private method. This method only returns methods declared in that particular class, not methods declared in any superclasses.

Notice the line in bold too. By calling Method.setAcessible(true) you turn off the access checks for this particular Method instance, for reflection only. Now you can access it even if it is private, protected or package scope, even if the caller is not part of those scopes. You still can’t access the method using normal code. The compiler won’t allow it.

 

Referenced by: http://tutorials.jenkov.com/java-reflection/private-fields-and-methods.html

 
Leave a comment

Posted by on October 12, 2011 in Java Pro

 

Using Java Reflection

By Glen McCluskey
January 1998

 

Reflection is a feature in the Java programming language. It allows an executing Java program to examine or “introspect” upon itself, and manipulate internal properties of the program. For example, it’s possible for a Java class to obtain the names of all its members and display them.

The ability to examine and manipulate a Java class from within itself may not sound like very much, but in other programming languages this feature simply doesn’t exist. For example, there is no way in a Pascal, C, or C++ program to obtain information about the functions defined within that program.

One tangible use of reflection is in JavaBeans, where software components can be manipulated visually via a builder tool. The tool uses reflection to obtain the properties of Java components (classes) as they are dynamically loaded.

A Simple Example

To see how reflection works, consider this simple example:

   import java.lang.reflect.*;

   public class DumpMethods {
      public static void main(String args[])
      {
         try {
            Class c = Class.forName(args[0]);
            Method m[] = c.getDeclaredMethods();
            for (int i = 0; i < m.length; i++)
            System.out.println(m[i].toString());
         }
         catch (Throwable e) {
            System.err.println(e);
         }
      }
   }

 

For an invocation of:

  java DumpMethods java.util.Stack

the output is:

  public java.lang.Object java.util.Stack.push(
    java.lang.Object)
   public synchronized 
     java.lang.Object java.util.Stack.pop()
   public synchronized
      java.lang.Object java.util.Stack.peek()
   public boolean java.util.Stack.empty()
   public synchronized 
     int java.util.Stack.search(java.lang.Object)

 

That is, the method names of class java.util.Stack are listed, along with their fully qualified parameter and return types.

This program loads the specified class using class.forName, and then calls getDeclaredMethods to retrieve the list of methods defined in the class. java.lang.reflect.Method is a class representing a single class method.

Setting Up to Use Reflection

The reflection classes, such as Method, are found in java.lang.reflect. There are three steps that must be followed to use these classes. The first step is to obtain a java.lang.Class object for the class that you want to manipulate. java.lang.Class is used to represent classes and interfaces in a running Java program.

One way of obtaining a Class object is to say:

   Class c = Class.forName("java.lang.String");

to get the Class object for String. Another approach is to use:

   Class c = int.class;

or

  Class c = Integer.TYPE;

to obtain Class information on fundamental types. The latter approach accesses the predefined TYPE field of the wrapper (such as Integer) for the fundamental type.

The second step is to call a method such as getDeclaredMethods, to get a list of all the methods declared by the class.

Once this information is in hand, then the third step is to use the reflection API to manipulate the information. For example, the sequence:

   Class c = Class.forName("java.lang.String");
   Method m[] = c.getDeclaredMethods();
   System.out.println(m[0].toString());

will display a textual representation of the first method declared in String.

In the examples below, the three steps are combined to present self contained illustrations of how to tackle specific applications using reflection.

Simulating the instanceof Operator

Once Class information is in hand, often the next step is to ask basic questions about the Class object. For example, the Class.isInstance method can be used to simulate the instanceofoperator:

   class A {}

   public class instance1 {
      public static void main(String args[])
      {
         try {
            Class cls = Class.forName("A");
            boolean b1 
              = cls.isInstance(new Integer(37));
            System.out.println(b1);
            boolean b2 = cls.isInstance(new A());
            System.out.println(b2);
         }
         catch (Throwable e) {
            System.err.println(e);
         }
      }
   }

In this example, a Class object for A is created, and then class instance objects are checked to see whether they are instances of AInteger(37) is not, but new A() is.

Finding Out About Methods of a Class

One of the most valuable and basic uses of reflection is to find out what methods are defined within a class. To do this the following code can be used:

   import java.lang.reflect.*;

   public class method1 {
      private int f1(
       Object p, int x) throws NullPointerException
      {
         if (p == null)
            throw new NullPointerException();
         return x;
      }

      public static void main(String args[])
      {
         try {
           Class cls = Class.forName("method1");

            Method methlist[] 
              = cls.getDeclaredMethods();
            for (int i = 0; i < methlist.length;
               i++) {  
               Method m = methlist[i];
               System.out.println("name 
                 = " + m.getName());
               System.out.println("decl class = " +
                              m.getDeclaringClass());
               Class pvec[] = m.getParameterTypes();
               for (int j = 0; j < pvec.length; j++)
                  System.out.println("
                   param #" + j + " " + pvec[j]);
               Class evec[] = m.getExceptionTypes();
               for (int j = 0; j < evec.length; j++)
                  System.out.println("exc #" + j 
                    + " " + evec[j]);
               System.out.println("return type = " +
                                  m.getReturnType());
               System.out.println("-----");
            }
         }
         catch (Throwable e) {
            System.err.println(e);
         }
      }
   }

The program first gets the Class description for method1, and then calls getDeclaredMethods to retrieve a list of Method objects, one for each method defined in the class. These include public, protected, package, and private methods. If you use getMethods in the program instead of getDeclaredMethods, you can also obtain information for inherited methods.

Once a list of the Method objects has been obtained, it’s simply a matter of displaying the information on parameter types, exception types, and the return type for each method. Each of these types, whether they are fundamental or class types, is in turn represented by a Class descriptor.

The output of the program is:

  name = f1
   decl class = class method1
   param #0 class java.lang.Object
   param #1 int
   exc #0 class java.lang.NullPointerException
   return type = int
   -----
   name = main
   decl class = class method1
   param #0 class [Ljava.lang.String;
   return type = void
   -----

 

Obtaining Information About Constructors

A similar approach is used to find out about the constructors of a class. For example:

 import java.lang.reflect.*;

   public class constructor1 {
      public constructor1()
      {
      }

      protected constructor1(int i, double d)
      {
      }

      public static void main(String args[])
      {
         try {
           Class cls = Class.forName("constructor1");

           Constructor ctorlist[]
               = cls.getDeclaredConstructors();
         for (int i = 0; i < ctorlist.length; i++) {
               Constructor ct = ctorlist[i];
               System.out.println("name 
                 = " + ct.getName());
               System.out.println("decl class = " +
                            ct.getDeclaringClass());
               Class pvec[] = ct.getParameterTypes();
               for (int j = 0; j < pvec.length; j++)
                  System.out.println("param #" 
                     + j + " " + pvec[j]);
               Class evec[] = ct.getExceptionTypes();
               for (int j = 0; j < evec.length; j++)
                  System.out.println(
                    "exc #" + j + " " + evec[j]);
               System.out.println("-----");
            }
          }
          catch (Throwable e) {
             System.err.println(e);
          }
      }
   }

There is no return-type information retrieved in this example, because constructors don’t really have a true return type.

When this program is run, the output is:

   name = constructor1
   decl class = class constructor1
   -----
   name = constructor1
   decl class = class constructor1
   param #0 int
   param #1 double
   -----

 

Finding Out About Class Fields

It’s also possible to find out which data fields are defined in a class. To do this, the following code can be used:

   import java.lang.reflect.*;

   public class field1 {
      private double d;
      public static final int i = 37;
      String s = "testing";

      public static void main(String args[])
      {
         try {
            Class cls = Class.forName("field1");

            Field fieldlist[] 
              = cls.getDeclaredFields();
            for (int i 
              = 0; i < fieldlist.length; i++) {
               Field fld = fieldlist[i];
               System.out.println("name
                  = " + fld.getName());
               System.out.println("decl class = " +
                           fld.getDeclaringClass());
               System.out.println("type
                  = " + fld.getType());
               int mod = fld.getModifiers();
               System.out.println("modifiers = " +
                          Modifier.toString(mod));
               System.out.println("-----");
            }
          }
          catch (Throwable e) {
             System.err.println(e);
          }
       }
   }

This example is similar to the previous ones. One new feature is the use of Modifier. This is a reflection class that represents the modifiers found on a field member, for example “private int“. The modifiers themselves are represented by an integer, and Modifier.toString is used to return a string representation in the “official” declaration order (such as “static” before “final“). The output of the program is:

  name = d
   decl class = class field1
   type = double
   modifiers = private
   -----
   name = i
   decl class = class field1
   type = int
   modifiers = public static final
   -----
   name = s
   decl class = class field1
   type = class java.lang.String
   modifiers =
   -----

As with methods, it’s possible to obtain information about just the fields declared in a class (getDeclaredFields), or to also get information about fields defined in superclasses (getFields).

Invoking Methods by Name

So far the examples that have been presented all relate to obtaining class information. But it’s also possible to use reflection in other ways, for example to invoke a method of a specified name.

To see how this works, consider the following example:

   import java.lang.reflect.*;

   public class method2 {
      public int add(int a, int b)
      {
         return a + b;
      }

      public static void main(String args[])
      {
         try {
           Class cls = Class.forName("method2");
           Class partypes[] = new Class[2];
            partypes[0] = Integer.TYPE;
            partypes[1] = Integer.TYPE;
            Method meth = cls.getMethod(
              "add", partypes);
            method2 methobj = new method2();
            Object arglist[] = new Object[2];
            arglist[0] = new Integer(37);
            arglist[1] = new Integer(47);
            Object retobj 
              = meth.invoke(methobj, arglist);
            Integer retval = (Integer)retobj;
            System.out.println(retval.intValue());
         }
         catch (Throwable e) {
            System.err.println(e);
         }
      }
   }

Suppose that a program wants to invoke the add method, but doesn’t know this until execution time. That is, the name of the method is specified during execution (this might be done by a JavaBeans development environment, for example). The above program shows a way of doing this.

getMethod is used to find a method in the class that has two integer parameter types and that has the appropriate name. Once this method has been found and captured into a Method object, it is invoked upon an object instance of the appropriate type. To invoke a method, a parameter list must be constructed, with the fundamental integer values 37 and 47 wrapped in Integer objects. The return value (84) is also wrapped in an Integer object.

Creating New Objects

There is no equivalent to method invocation for constructors, because invoking a constructor is equivalent to creating a new object (to be the most precise, creating a new object involves both memory allocation and object construction). So the nearest equivalent to the previous example is to say:

   import java.lang.reflect.*;

   public class constructor2 {
      public constructor2()
      {
      }

      public constructor2(int a, int b)
      {
         System.out.println(
           "a = " + a + " b = " + b);
      }

      public static void main(String args[])
      {
         try {
           Class cls = Class.forName("constructor2");
           Class partypes[] = new Class[2];
            partypes[0] = Integer.TYPE;
            partypes[1] = Integer.TYPE;
            Constructor ct 
              = cls.getConstructor(partypes);
            Object arglist[] = new Object[2];
            arglist[0] = new Integer(37);
            arglist[1] = new Integer(47);
            Object retobj = ct.newInstance(arglist);
         }
         catch (Throwable e) {
            System.err.println(e);
         }
      }
   }

which finds a constructor that handles the specified parameter types and invokes it, to create a new instance of the object. The value of this approach is that it’s purely dynamic, with constructor lookup and invocation at execution time, rather than at compilation time.

Changing Values of Fields

Another use of reflection is to change the values of data fields in objects. The value of this is again derived from the dynamic nature of reflection, where a field can be looked up by name in an executing program and then have its value changed. This is illustrated by the following example:

   import java.lang.reflect.*;

   public class field2 {
      public double d;

      public static void main(String args[])
      {
         try {
            Class cls = Class.forName("field2");
            Field fld = cls.getField("d");
            field2 f2obj = new field2();
            System.out.println("d = " + f2obj.d);
            fld.setDouble(f2obj, 12.34);
            System.out.println("d = " + f2obj.d);
         }
         catch (Throwable e) {
            System.err.println(e);
         }
      }
   }

In this example, the d field has its value set to 12.34.

Using Arrays

One final use of reflection is in creating and manipulating arrays. Arrays in the Java language are a specialized type of class, and an array reference can be assigned to an Object reference.

To see how arrays work, consider the following example:

   import java.lang.reflect.*;

   public class array1 {
      public static void main(String args[])
      {
         try {
            Class cls = Class.forName(
              "java.lang.String");
            Object arr = Array.newInstance(cls, 10);
            Array.set(arr, 5, "this is a test");
            String s = (String)Array.get(arr, 5);
            System.out.println(s);
         }
         catch (Throwable e) {
            System.err.println(e);
         }
      }
   }

This example creates a 10-long array of Strings, and then sets location 5 in the array to a string value. The value is retrieved and displayed.

A more complex manipulation of arrays is illustrated by the following code:

   import java.lang.reflect.*;

   public class array2 {
      public static void main(String args[])
      {
         int dims[] = new int[]{5, 10, 15};
         Object arr 
           = Array.newInstance(Integer.TYPE, dims);

         Object arrobj = Array.get(arr, 3);
         Class cls = 
           arrobj.getClass().getComponentType();
         System.out.println(cls);
         arrobj = Array.get(arrobj, 5);
         Array.setInt(arrobj, 10, 37);

         int arrcast[][][] = (int[][][])arr;
         System.out.println(arrcast[3][5][10]);
      }
   }

This example creates a 5 x 10 x 15 array of ints, and then proceeds to set location [3][5][10] in the array to the value 37. Note here that a multi-dimensional array is actually an array of arrays, so that, for example, after the first Array.get, the result in arrobj is a 10 x 15 array. This is peeled back once again to obtain a 15-long array, and the 10th slot in that array is set using Array.setInt.

Note that the type of array that is created is dynamic, and does not have to be known at compile time.

Summary

Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and allows for their manipulation within an executing Java program. This feature is extremely powerful and has no equivalent in other conventional languages such as C, C++, Fortran, or Pascal. Coffecup Logo

Glen McCluskey has focused on programming languages since 1988. He consults in the areas of Java and C++ performance, testing, and technical documentation.

 

Referenced by: http://java.sun.com/developer/technicalArticles/ALT/Reflection/

 
Leave a comment

Posted by on October 11, 2011 in Java Pro

 

Make Java Application as Windows Service

Let’s say that we want to create a Windows Installer package for the included Java Service example. This tutorial will present in detail how to achieve this goal. In order to replicate it on your own machine, you need to have a (latest) Sun JDK installed.

Before you start the tutorial download and unzip the Java Service Example. It contains all the files necessary to accomplish this tutorial.

1. Prepare a Java application for running as a service

You have the choice of using the supplied example application or making your own. In order for a Java application to work correctly as a service you must implement 2 methods in its main class:

public static void main(String argv[])
{
  // implementation goes here
}

public static void stop()
{
  // implementation goes here
}

The main() method will be called when the service starts and the stop() method will be called when service must stop or the computer is shutting down.

2. Create project

Start Advanced Installer by selecting it from the “Start” menu. Launching Advanced Installer automatically starts a new installation project. Choose “Java” > “Java Application” as the project type.

New Project

Save A good idea is to save and name the project at this point. Use the “Save” menu item under the “File” menu or the Ctrl+S keyboard shortcut and let’s name it javaserviceexample.aip.

3. Enter Product Details

Product Details

Please note that these details are completely fictive.

4. Set Install Parameters

Install Parameters Get to the Install Parameters page by clicking “Install Parameters” on the left side page menu. We won’t change anything here, leaving everything to their default values.

5. Add Installation Files

Files and Folders Go to the Files and Folders page by clicking on “Files and Folders” on the left side page menu.

Add Folder Right click “Application Folder” and select “Add Files”. Browse to where you unzipped the Java Service example then go to the lib folder and select the Java Services example jar archive “javaservice.jar”. Click Ok.

Files, Folders and Shortcuts

6. Define Java Products

Java  Products Go to the Java Products page by clicking on “Java Products” on the left side page menu.

New  Java Product Create a new [ Java Product ] by clicking on the New Product toolbar button. Let’s call it javaservice.

Java Products

Click on the [ Add JAR(s)… ] button and browse to and select the javaservice.jar file. Click Ok.

Edit the Main class to: com.caphyon.service.JavaService.

At the application type select “Win32 Service”.

Product Settings

Now a new file has appeared in the Files and Folders Page: javaservice.exe.

NoteIf the service terminates unexpectedly from time to time or when the user logs off, the Java Virtual Machine may receive incorrect signals. This can be fixed by using the Reduced usage of operating-system signals (-Xrs) option in the Edit JVM Parameters dialog (it can be launched from the Virtual Machine tab).

7. Define the Service

Services Go to the Services page by clicking on “Services” in the Project Details.

7.1 Install a new service

New Service Click on “Services to Install” and select “New Service Installation”. In the “Choose Instalation Dialog” click on “Application Folder” and select “javaservice.exe”.

New Java Service

7.2 Enter service properties

Leave Service Name unchanged.

Edit the Display Name: Java Service Example.

Edit the Description: This a Java Service Example.

Leave the Service Parameters, Service context and Service Account unchanged.

Installed Service Properties

7.3 Setup the control actions

New Service Control Operation Right click on “Control Action” and select “New Service Operation”.

Edit the Service Name to: javaservice.exe.

Leave anything else unchanged.

Sevice Control Parameters

8. Build

Build Click on the [ Build ] toolbar button.

9. Run, test and remove

Click on the [ Run ] toolbar button to run and test the MSI you created. After installation you should have a new service installed.

To test the application open console and enter the following command: telnet localhost 4444. You should see:

Java Service is running
                        
Connection to host lost

You also can build Java Service Example msi package using ant. Open a console window and change current directory to the directory where you unzipped the Java Service example archive. Execute the following command: ant msi.

To remove the installed package, simply Run it again and select Remove. That’s it!

Referenced by: http://www.advancedinstaller.com/user-guide/tutorial-java-service.html

 
Leave a comment

Posted by on April 8, 2010 in Java Pro