martedì 10 febbraio 2009

JavaApplet used to print over Serial Port

What I want to share with you today is a way to print on a serial printer (in my case I used a barcode printer).

Anyone is starting reading this post could thik: "Yes but is not too difficult to use serial port with Java". Yes but you have to think to another point: we are talking of a web-application and, our printer, is linked to the client (naturally... maybe my server is not directly accessible). And another interesting point is that our installed JRE could blocked the access to computer ports. I say "could" but it surely does if you haven't set the "policy" file or add necessary library to the JRE.

Anyway... here you are my experience.

Starting Point
The starting point was locate the necessary libraries, and after some tests with official Sun javax.comm I've decided to use RXTX library because they sort out with all necessary to use them on all operating systems.

And now... all is very simple to do.

Applet
As I said before, we need "something" printed on client machine. So we surely need a simple applet, maybe hidden.

Inside init method you just need to initialize your ports.

@Override
public void init() {
try {
Enumeration portList = CommPortIdentifier.getPortIdentifiers();

if (portList.hasMoreElements()) {
this.portId = ((CommPortIdentifier) portList.nextElement());
}
} catch (Exception e) {
e.printStackTrace();
}

//Opening port to test
try {
CommPort serialPort = this.portId.open("SerialPort", 200);
serialPort.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}


The second part of this code Opening port to test is necessary to let your applet always ready to print. During my tests if I didn't try to open the serial port after getting it sometime it does not work.


After this thing, what you need is a simple method to print what you need. I post here my code that, as I said, is used to print a barcode.

public void printBarCode(String code) {
try {
CommPort serialPort = this.portId.open("SerialPort", 200);

PrintStream out = new PrintStream(serialPort.getOutputStream(), true);
out.println("N\n");
out.println("D13\n");
out.println("S2\n");
out.println("B240,2,0,K,4,5,83,B,\"" + code + "\"\n");
out.println("P1\n");

out.close();

serialPort.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}


All information I'm sending to print was getting from EPL print manual. Are just information you need to set-up printer, page and barcode style.

If you need anything special you can consider your applet ready to use. You may just package it in a jar and add the jar to your webserver / web-application.

Adding applet to a page
Inside your page you can just add the applet using applet tag or object tag. In my case I have used applet one because the object give me some problems. In all tests I've done with applet works correctly both on IE and Firefox with windows and Linux.

<applet name="barcodeprinter" 
id="barcodeprinter"
archive="/BarCodeApplet.jar"
code="com.bytecode.priterapplet.BarCodePrinter"
MAYSCRIPT="true"
style="width: 1px; height: 1px; background: white;">
</applet>


Note the mayscript parameter. Is used to let your browser (javascript) to interact with your applet. In fact if you don't add it what you can do is just load a page with an applet that starts printing a "static text". Not so useful!

More interesting is sure letting the user the selection of the "code" to print. And you can make this with a very simple javascript code.

<script type="text/javascript">
function inventario(code) {
var applet = document.getElementById("barcodeprinter");
if(code != '') {
applet.printBarCode(code);
}
}
</script>


And to call your javascript

<a href="#" onclick="inventario('selectedCode');">Selected Element</a>


Configuring client
If you will try to use your applet without setting your JRE you couldn't print anything. What you need is just get RXTXcomm.jar to copy in JRE_HOME/lib/ext folder, and the correct library (DLL for Windows, .so for linux) and copy it in JRE_HOME/bin folder. For Mac the procedure is a little bit different but you can find the instruction for all operating system directly inside the file you have downloaded from RXTX website.

Enhancements
What I've tried after this thing is the dynamic configuration of the client. What you can do is copy the DLL/SO file in a client folder, load dynamically into JRE but, anyway, you have to set, at least, the .policy file on the client. Is a security setting made inside Java: from a webapplet you can't doing what you want on a client computer.

Anyway here you are a little example of what I've done

if (System.getProperty("os.name").toUpperCase().contains("WINDOWS")) {
libraryName = DLL_SERIAL_NAME;
libraryFile = System.getProperty("java.io.tmpdir") + DLL_SERIAL_NAME;
} else if (System.getProperty("os.name").toUpperCase().contains("LINUX")) {
if (System.getProperty("os.arch").contains("i386")) {
libraryName = SO_SERIAL_NAME_32;
} else {
libraryName = SO_SERIAL_NAME_64;
}

char fileSeparator = System.getProperty("file.separator").charAt(0);
libraryFile = System.getProperty("java.io.tmpdir") + fileSeparator + SO_SERIAL_NAME;
}

if (!(verifyLibraryExistence(libraryFile))) {
copyResourceFromJar(libraryFile, libraryName);
}
try {
System.load(libraryFile);
} catch (Exception e) {
e.printStackTrace();
}


DLL and so files are contained in the applet JAR.

Hope to be useful to anyone. And write to me if you have any kind of problem!

venerdì 9 gennaio 2009

Symbolic v.1.2.1

I'm happy to announce you that Symbolic 1.2.1 is finally sort out!!

In this minor release we haven't add any kind of new features, but we worked a lot to make the application stable and stronger.

The new features added are listed below:
- Update graphical icons
- Reviewed running operations window
- Solved bugs during script execution
- Moved engine to use Func 0.23+
- Added some basic operations
- Create a symbolic-setup scripts that help you to setup acls on func folders
- Solved some bugs in VirtualManager execution
- Create a Makefile to simplify the build process

To make a correct installation of the application you can follow this tutorial.

Enjoy!
Any kind of comment is welcome!

giovedì 23 ottobre 2008

Google Developer Day 2008 - Milan

For the second year, Google has decide to make a Google Developer Day in Milan. For me was the first time at a Google event and I found it really great.

I arrived at the Hotel got for the event (Nhow Hotel, Via Tortona 35 in Milan) at 9 o'clock in the morning, and there was a huge number of person waiting to get into hall. So I start with a little queue (about 15 minutes waiting for solve my registration) and hoping to enter. In fact I didn't make the registration for the event but I was there to substitute a colleague: no one has asked me any king of document that could prove that I'm the person I was saying to be! :) So really cool... for a day I wasn't me!! :)

Anyway... after registration where I choose my session (I got all sessions I decided to see... not bad ;)) I start "walking" on the hall, where there was a coffee break for a little breakfast, and looking for the programmers present to the event. As I imagined I met some person I knew! (the IT is a little world!! :P)
At 10 o'clock all people start moving in the "light blue room" to listen the little introduction from the Italian Marketing Manager (I can't remember the name but... was a woman!) and something about Google technologies listening Brian Fitzpatrick, a google software engineer. No news listing this presentation: the message send to all developer was "Google is the best!" ;)

App Engine (Kevin Gibbs)
Introduction to Google App Engine technology. Basically you can write your application (in different language) and "deploy" it on Google systems. You have only some limitations in your "free account" but Google can assure you that all applications are completely scalable: if you need more resources (application on cluster) google gives them to you. What you need to do, is just to write your code. You also have some API that help you to make some operations, for example imaging manipulation, and using this API you have an operation that, if it needs more cpu time, for example, it could has it!
Not bad!! Naturally the best thing is the possibility to test this technology for free!
I've tried to ask something about cluster management (if we can for example manage the http session synchronization) and the answer wans't a "NO" but something that was walking about "NO"! :)

Google Data API (Jochen Hartmann)
This session was really quiet. A panorama about Google Data API, written for many different languages, that you can use to make in communication your application with Google World! Picasa to get Photos, Google Maps, YouTube and all other things.
I've no idea on how I could use all these things... but now I know what can I do and how! :P

Geo (Nicola Ferioli)
Wow an Italian Talk!! I was exited just before the talk because, maybe (or surely) for the presence of an italian speaker, during exposition there were many questions (so many interruption of the talk) and at the end of the talk I didn't have time to talk with Nicola about geo. I hope I'll have time to talk with him in the future.
All of us have tried to use Google Earth and surely Google Maps, here the presentation was about the integration of these tools inside other Web Application. What you can do is really impressive. You can simply insert a map in your page and then add to this "image" a second layer with some markers to shown some point-of-interest on your map. Naturally generated map is the same you can use on google web site, so you can navigate it and change details and zoom levels.
If you "don't like" (or better you don't need) the Google Map, you can also change the "skin" you get from google with your own pictures. So what you get from google is only the engine to navigate your image and add over it some markers.

Same things could do using the newest Earth plugin: you can insert in you web page an "image" get from Earth and navigate it!

Intro to Android

Android was the most impressive talk I've seen to GDD. The real "presentation" of operating system was just about the main features offered by Android, what has gotten my attention was the "demo application" that speaker (unfortunately I can't remember the name) has realized using eclipse and android plugin. In 30 minutes, showing also all the features offered by eclipse android plugin, he has created a simple Java application that can read contacts from phone contacts list and show results to the user.
For a Java programmer is really simple to create a new application for the phone and, in my opinion, this will be the cool feature to get the market and move many users to this new phone (both Symbian users and iPhone users ;)).
Yesterday (22 Oct 2008) the first Google Phone (with HTC hardware) is sorted out in the US... We have just to wait to buy phone also here in europe! :)

Was a really cool events and I have to thanks my colleague Luca for the opportunity! ;)

giovedì 4 settembre 2008

Going to FudCon


It's time to get my baggage and take the plane for Brno.

See you there guys!

mercoledì 30 luglio 2008

Grails - Dynamic Plugins - Isolated Classloader

To prevent a possible jars conflict during dynamic plugin execution (what I was talking about in my previous post), I found a simple solution that I'm pasting for you here:

class DefaultPluginJob {

static triggers = { }

static cachedClassLoader = [:]

def execute(context) {

def libraryFolder = context.mergedJobDataMap.get("libraryFolder")

if (!cachedClassLoader[context.mergedJobDataMap.get("jobName")]) {
log.debug "Constructing class loader for ${context.mergedJobDataMap.get("jobName")}"
def urls = []
libraryFolder?.eachFile {library ->
log.debug "Adding file ${library}"
urls.add(library.toURL())
}
cachedClassLoader[context.mergedJobDataMap.get("jobName")] = new URLClassLoader(urls as URL[], this.class.classLoader)
}

def file = context.mergedJobDataMap.get("scriptFile")

Binding binding = new Binding(context.mergedJobDataMap);
GroovyShell shell = new GroovyShell(cachedClassLoader[context.mergedJobDataMap.get("jobName")], binding);
def scriptResult = shell.evaluate(file.text);

}
}

A new URLClassLoader will be created for each script that need to be run from my job, and it will contain a copy of parent class loader and new jars needed for the script execution.

What you can find here is the current solution I'm using in my application: all classloaders are cached in a static map (thanks again to Sergey for suggestion ;)) and passed to GroovyShell for script exection. Using cache for classloader granted that I've only one classloader generation for each script (and not one for each job execution). You loose memory to get perfermance! ;)

Waiting for comments about this way to run a java web application! :)

sabato 26 luglio 2008

Grails - Dynamic Plugins for your applications

The new functionality offers from Groovy/Grails make you able to write a very dynamical application and the possibility to add some new features to your web application at run-time!! Naturally we are exiting a "little bit" from JEE standards where our library/scritps/class and so on, must be in your war or provided from application server.
What I think about this, is that this way to see the development is a little bit old and could bring java to death! I'm dramatic, I know, but there is lot of confusion inside java, java standard and all java project.
It's time to change!! :)

Anyway...

What I'll explain is the way that we are using to add plugins (some functions) to OpenSymbolic, after application installation and, if you want, after webserver startup (I don't know what JBoss thinks about this... I'll do some test when all will be ready).

Our goal was to obtain a way to add some schedulable functions (Quartz Job) to our application leaving to user the decision about which he needs and which not (in a future article we will see the real usage in Symbolic).

First step
Question: How can I add a Job Dynamically to my scheduler?
Answer: at the moment I can't! :(

Solution: I called Sergey Nebolsin, the Quartz plugin developer, exposing my problem, and in ONE NIGHT (underline well ONE), he send me the implementation.
Lesson learned: If I need something for the following day... I will have to call Sergey!! :P (Really thanks again for your work and help Sergey!!)

Second step
Writing a bit of code to see if I can really do what I'm thinking.

Here what I have.

All my plugins will be contained in a specific folder on my machine (configured in configuration file of my application).
/etc/symbolic/plugins
-> /nagios_plugin
-> /msn_plugin
-> /dont_know_plugin

Each of these folders contains the file I need: in my test a configuration file and one script file.
So... with a simple script I could try to scan these folders look for what I need.
import org.codehaus.groovy.grails.commons.ConfigurationHolder

class PluginService {

boolean transactional = false

static CONFIG_FILE_EXT = 'conf'
static SCRIPT_FILE_EXT = 'groovy'
static LIB_FOLDER = 'lib'

public void init() {
//Scan Plugins Folder
def pluginsFolder = ConfigurationHolder.config.plugin.folder
log.debug "Scanning plugin folder: ${pluginsFolder}"
if (pluginsFolder) {
new File(pluginsFolder).eachDir {dir ->
log.debug "Directory found: ${dir}"
def dataMap = [:]

//Read Plugin File and configuring it
dir.eachFile {file ->
if (file.isFile()) {
if (file.name.contains(CONFIG_FILE_EXT)) {
log.debug "File ${file.name} is the configuration file"
def pluginConfiguration = readConfigFile(file)
dataMap['pluginName'] = pluginConfiguration.get("job.name")
dataMap['cronString'] = pluginConfiguration.get("job.cron")
} else if (file.name.contains(SCRIPT_FILE_EXT)) {
log.debug "File ${file.name} is the script file"
dataMap['scriptFile'] = file
} else {
log.debug "File ${file.name} will be ignored!"
}
} else {
if (file.name.equals(LIB_FOLDER)) {
log.debug "Lib folder found... adding jars to classpath."
}
}
}
DefaultPluginJob.schedule(dataMap['cronString'], dataMap)
}
}

else {
logger.info "No plugins folder set. Nothing to load!"
}

}


def readConfigFile = {file ->
Properties prop = new Properties()
if (file) {
prop.load (new FileInputStream(file))
}
prop
}
}

It's just a simple test... there are many improvements to do! ;)

Class "DefaultPluginJob" is a simple Quartz Job, that you can create in a standard grails way, and, with a new plugin release made by Sergey, it has some static methods that you can use to add your job to your quartz scheduler!

Here is the code of Job:
import org.quartz.JobDataMap
import org.quartz.JobExecutionContext

class DefaultPluginJob {

static triggers = { }

def execute(context) {

String instName = context.getJobDetail().getName();
String instGroup = context.getJobDetail().getGroup();
def file = context.mergedJobDataMap.get("scriptFile")

Binding binding = new Binding();
GroovyShell shell = new GroovyShell(binding);

def scriptResult = shell.evaluate(file.text);

}
}

It seems very simple, no? :)

Third step
To create a real extension of your application, you may need to add also some libraries used by your script: you cannot add all existing java libraries to your application because someone would create a plugin that will use that libraries! ;)

A very simple way we have found to solve this problem is adding a lib sub-folder to your plugin folder, where you can put all your libraries.
The plugin server, scanning folders, will add your jars to root class loader in this way:
this.class.classLoader.rootLoader.addURL(new URL("${file}"))

By now you can use all classes contained in your added jar files! :D

Future...
What I need to solve now, is a way to prevent jar conflict. Add all to root class loader, in fact, could make some problems to your application or simply to your other plugins.
I think that a solution could be write something inside your job, that will add your library only to your job instances during (before) execution of the script!
If anyone has any ideas about that... is welcome! :P

giovedì 24 luglio 2008

Symbolic - Operations Runner

Symbolic engine, or OperationRunner, is something like what we have seen for the scripts: a couple of job/thread that going in polling over database, look for ready operation, or completed (success/failed) operations.
All this operation will be completely asynchronous both for user and symbolic application: a ControllerJob will call each "n" seconds to verify the state of ran operation.



  1. Select machine(s), decide which operation he want, and complete (if required) the parameters needed for the execution
  2. An entry is stored in database and set in "ready state"
  3. RunnerJob (is not the same job used to run scripts!) check, each "x" seconds, if there's any operation to run.
  4. When it finds something, using func api, he call func and change the operation status in database: running state
  5. Func, through func-transmit script, will call required minion creating an "async job" (the job id will be returned to RunnerJob and stored in database)
  6. Another job, the ControllerJob, verifies if there is any running operation (contacting database) and, using stored job id, it asks to Func the state of that job
  7. When it receives a "complete job" response (could be success or failed) store the information in database setting also the status to correct value (success/error)
  8. User can see the result for the operation he called.