Back to Contents


How to Call Java APIs from Genero


Overview

This tutorial explains how to call a Java library from Genero, using Genero and Java Web services. This can easily be done using the Java JAX-WS framework and without any strong linkage between Genero and Java. We will use a Java barcode creation library to build a picture from a code.

Note: Accessing a .NET library could be done in the same manner.

Back to the top


Prerequisites

Back to the top


Using the barcode library

The barcode library is composed of two libraries -- one for building a barcode image from a numeric code, and one for reading a barcode image to return the numeric code. This section depends on the library you want to use in Genero.

In our tutorial, we create two functions called buildImage and readImage; the Java implementation is below:

try {
Barcode builder=new Barcode();
builder.setType(GetBarcodeBuilderType(type));
builder.setData(data);
builder.setAddCheckSum(true);
ByteArrayOutputStream out=new ByteArrayOutputStream();
if (builder.createBarcodeImage(out)) {
byte[] ret = out.toByteArray();
return ret;
} else {
return null;
}
} catch(Exception e) {
return null;
}
try {
File f=new File("tmp.jpg");
FileOutputStream stream=new FileOutputStream(f);
stream.write(img);
stream.close();
String[] datas = BarcodeReader.read(f, GetBarcodeReaderType(type));
if (datas==null) {
return null;
} else {
String ret = datas[0];
return ret;
}
} catch (Exception e) {
return null;
}
The following two functions convert the type of a code bar to the type expected by the library:
private int GetBarcodeBuilderType(String str) {
if (str.equals("CODABAR")) {
return Barcode.CODABAR;
} else if (str.equals("CODE11")) {
return Barcode.CODE11;
} else if (str.equals("CODE128")) {
return Barcode.CODE128;
} else if (str.equals("CODE128A")) {
return Barcode.CODE128A;
} else if (str.equals("CODE128B")) {
return Barcode.CODE128B;
} else if (str.equals("CODE128C")) {
return Barcode.CODE128C;
} else if (str.equals("CODE2OF5")) {
return Barcode.CODE2OF5;
} else if (str.equals("CODE39")) {
return Barcode.CODE39;
} else if (str.equals("CODE39EX")) {
return Barcode.CODE39EX;
} else if (str.equals("CODE93")) {
return Barcode.CODE93;
} else if (str.equals("CODE93EX")) {
return Barcode.CODE93EX;
} else if (str.equals("EAN13")) {
return Barcode.EAN13;
} else if (str.equals("EAN13_2")) {
return Barcode.EAN13_2;
} else if (str.equals("EAN13_5")) {
return Barcode.EAN13_5;
} else if (str.equals("EAN8")) {
return Barcode.EAN8;
} else if (str.equals("EAN8_2")) {
return Barcode.EAN8_2;
} else if (str.equals("EAN8_5")) {
return Barcode.EAN8_5;
} else if (str.equals("INTERLEAVED25")) {
return Barcode.INTERLEAVED25;
} else if (str.equals("ITF14")) {
return Barcode.ITF14;
} else if (str.equals("ONECODE")) {
return Barcode.ONECODE;
} else if (str.equals("PLANET")) {
return Barcode.PLANET;
} else if (str.equals("POSTNET")) {
return Barcode.POSTNET;
} else if (str.equals("RM4SCC")) {
return Barcode.RM4SCC;
} else if (str.equals("UPCA")) {
return Barcode.UPCA;
} else if (str.equals("UPCE")) {
return Barcode.UPCE;
} else {
return -1;
}
}
private int GetBarcodeReaderType(String str) {
if (str.equals("CODABAR")) {
return BarcodeReader.CODABAR;
} else if (str.equals("CODE11")) {
return BarcodeReader.CODE11;
} else if (str.equals("CODE128")) {
return BarcodeReader.CODE128;
} else if (str.equals("CODE39")) {
return BarcodeReader.CODE39;
} else if (str.equals("CODE39EX")) {
return BarcodeReader.CODE39EX;
} else if (str.equals("CODE93")) {
return BarcodeReader.CODE93;
} else if (str.equals("DATAMATRIX")) {
return BarcodeReader.DATAMATRIX;
} else if (str.equals("EAN13")) {
return BarcodeReader.EAN13;
} else if (str.equals("EAN8")) {
return BarcodeReader.EAN8;
} else if (str.equals("INTERLEAVED25")) {
return BarcodeReader.INTERLEAVED25;
} else if (str.equals("ITF14")) {
return BarcodeReader.ITF14;
} else if (str.equals("ONECODE")) {
return BarcodeReader.ONECODE;
} else if (str.equals("PLANET")) {
return BarcodeReader.PLANET;
} else if (str.equals("POSTNET")) {
return BarcodeReader.POSTNET;
} else if (str.equals("QRCODE")) {
return BarcodeReader.QRCODE;
} else if (str.equals("RM4SCC")) {
return BarcodeReader.RM4SCC;
} else if (str.equals("RSS14")) {
return BarcodeReader.RSS14;
} else if (str.equals("RSSLIMITED")) {
return BarcodeReader.RSSLIMITED;
} else if (str.equals("UPCA")) {
return BarcodeReader.UPCA;
} else if (str.equals("UPCE")) {
return BarcodeReader.UPCE;
} else {
return -1;
}
}

Back to the top


Calling Java from Genero

The integration of one or several Java libraries with multiple methods in a Genero application can be performed as described below:

Step 1: Write a new java class

Instead of writing the functions in 4GL, you simply need to write them in a Java class with the methods you want to use in 4GL as described below. In our example, the two functions are buildImage and readImage. And of course, don't forget to import the necessary Java import instructions.

import com.barcodelib.barcodereader.BarcodeReader;
import com.barcodelib.barcode.Barcode;
import java.io.*;
 
import javax.jws.*;
import javax.jws.soap.SOAPBinding;
import javax.xml.ws.Endpoint;
 
public class BarcodeService {
public byte[] buildImage(String type,String data)
{
/*BUILDIMAGE IMPLEMENTATION CODE DESCRIBED ABOVE*/
}
public String readImage(String type,byte[] img)
{ { { {
/*READIMAGE IMPLEMENTATION CODE DESCRIBED ABOVE*/
} }
}

Notice that if you want the service to run standalone, you must also add following the main method to tell the system the port number on which the service will run:

public static void main(String[] args)
{
String endpointUri = "http://localhost:9090/";
Endpoint.publish(endpointUri, new BarcodeService ());
System.out.println("BarcodeService started at " + endpointUri);
}

Step 2 : Transform the Java class in a Web Service

To transform the previous java class in a Web Service, simply add a WebService annotation:

@WebService(targetNamespace = "http://www.mycompany.com/barcode",
name="Barcode",
serviceName="BarcodeService")
public class BarcodeService {
...
}

This defines all public and non static methods of the class as operations of the BarcodeService Web Service.

Step 3 : Start the service

Compile the previously created java class, and run it.

Commands to compile and execute the service in standalone mode:

$ javac BarcodeService.java
$ java BarcodeService

Once the service is started, it is ready to accept requests and you can also retrieve its WSDL at following URL:

http://localhost/9090/BarcodeService?WSDL

Note: If you want the service to be started on a web server, you must deploy it first using Eclipse or the Web Server deployment tools.

Step 4 : Generate 4GL stub to access the Java library

Use the fglwsdl tool to generate the client stub to access the BarcodeService:

$ fglwsdl http://localhost:9090/BarcodeService?WSDL

This will create two 4GL files that must be compiled and linked into your 4GL application in order to call the Java barcode library functions. These files contain the 4GL interface to access the Java library where you will find the two functions, readImage and buildImage, defined in 4GL.

Step 5 : Modify your 4GL application

The last step is to modify the existing application where you want to use the Java library, by calling the 4GL functions generated in the stub. Then compile your application and the previously generated stubs, and link everything together.

Your application is now ready to use the different features of your Java library.

Back to the top


Example 4GL program

This program calls the buildImage function of the Barcode Java library.

GLOBALS "BarcodeService_BarcodePort.inc"
 
MAIN
DEFINE wsstatus INTEGER
IF num_args() != 3 THEN
CALL ExitHelp() END IF
LET ns1buildImage.arg0 = arg_val(1)
LET ns1buildImage.arg1 = arg_val(2)
LOCATE ns1buildImageResponse.return IN MEMORY
LET wsstatus = buildImage_g()
IF wsstatus <> 0 THEN DISPLAY "Error ("||wsError.code||") : ",wsError.description
ELSE IF IF ns1buildImageResponse.return IS NULL THEN
DISPLAY "Encoding failed"
ELSE
CALL ns1buildImageResponse.return.writeFile(arg_val(3))
END IF
END IF
FREE ns1buildImageResponse.return
 
END MAIN
 
FUNCTION ExitHelp()
DISPLAY arg_val(0)||" <type> <data> <filename>"
DISPLAY "type : barcode type such as EAN8 or CODE128"
DISPLAY "data : data to be encoded with a barcode [0-9A-D]"
DISPLAY "filename : resulting image filename"
DISPLAY "exemple : createImage EAN8 12358723A mybarcode.jpg"
EXIT PROGRAM (-1)
END FUNCTION

Back to the top


Conclusion

You call any Java library from Genero using Web Services, and without a strong dependency to a JVM. This follows SOA principles - it allows you to reuse the Java library in another 4GL application without any new development, you can update the Java part without recompiling any 4GL sources, and integrate any function available from a SOA platform.

Back to the top