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 codebar creation library to build a picture from a code.
Note: Accessing a .NET library could be done in the same manner.
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; } }
The integration of one or several Java libraries with multiple methods in a Genero application can be performed as described below:
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); }
To transform the previous java class in a Web Service, simply add a WebService annotation:
@WebService(targetNamespace = "http://www.4js.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.
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?WSDLNote: 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.
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.
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.
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 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 : codebar type such as EAN8 or CODE128" DISPLAY "data : data to be encoded with a codebar [0-9A-D]" DISPLAY "filename : resulting image filename" DISPLAY "exemple : createImage EAN8 12358723A mybarcode.jpg" EXIT PROGRAM (-1) END FUNCTION
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.