Pages

Wednesday, September 21, 2011

StAX perser to handle HTML elements in XML data

The StAX API provides methods for iterative, event based parsing of XML documents. XML documents are treated as a series of events. Moreover the StAX API is bidirectional and that enables both reading and writing of XML documents.

The top level interface that provides methods to parse XML Events is XMLEventReader. To get a reference to the XMLEventReader you use the XMLInputFactory class that defines and abstract implementation of a factory for getting streams. Here is how you do it:

// This can be any InputStream
InputStream is;
XMLInputFactory factory = XMLInputFactory.newInstance();
// Now use the factory to get the EventReader from the InputStream
XMLEventReader eventReader = factory.createXMLEventReader(is);

Now you can parse the whole XML document be using the method provided in the reader. i.e.

// Get the next Event from EventReader
event = eventReader.peek();
if (event.isCharacters()){
// Get the data if it is a Character Event
event = eventReader.nextEvent();
      data  = ((Characters) event).getData();
}

This all works brilliantly for any XML document until you encounter some HTML elements somewhere in the XML Data, such as & etc. That’s where it all goes wrong and the parser fails to parse the data after the HTML element.

This is because when StAX event parser encounters & (and other similar characters) it converts it correctly to “&” but it treats the data as three separate events; all the characters before the escape character, the escape character itself, and all the characters after the escape character.

As a result using the code above will return only the first event as data of that element. For example if you have “Procter & Gamble” in your element, the call to the getData() method will only return “Procter ” as data.

To get the whole data, you need to set the property “javax.xml.stream.isCoalescing” to true in the factory class. The default value of this property is false. Setting this property to TRUE will requires the processor to coalesce adjacent character data.

All you need to do is to add another line of code before you get the event reader from the factory as follows:

// This can be any InputStream
InputStream is;
XMLInputFactory factory = XMLInputFactory.newInstance();
// Set this property to handle special HTML characters like & etc.
factory.setProperty(XMLInputFactory.IS_COALESCING, true);
// Now use the factory to get the EventReader from the InputStream
XMLEventReader eventReader = factory.createXMLEventReader(is);

The resulting event reader will now handle the HTML character codes successfully.

This is the tutorial on how to use the StAX API.

Wednesday, June 1, 2011

Creating a Windows Service for Glassfish V2.

I can think of quite a few reasons why you want to create a service for your Glassfish domains. With the Glassfish V3 release, it is now very simple to create a service at the install time and the installer will do the work for you. The V2 however is a different story.

That said, it is still very easy to create a service for Glassfish V2 domains. The easiest way is to use the sc.exe windows utility to create and remove services. You can find more details about this command here.

Usage is fairly simple. Open the command prompt as administrator and type in the following command:
sc create [service name] binPath= "[Path to appservService.exe] \"[path to asadmin.bat] start-domain [domain name]\" \"[path to asadmin.bat] stop-domain [domain name]\"" start= auto DisplayName= "[display name]"

Just replace everything within the [] with your details. Noticeable things here are the [service name] and [display name]. The service name will be the ID of your service whereas the display name is the name you will see on the Services panel under administrative tools.
For example here is the sample command with full path names according to the installation on my machine:
sc create GFService binPath= "C:\software\glassfish\lib\appservService.exe \"C:\software\glassfish\bin\asadmin.bat start-domain domain1\" \"C:\software\glassfish\bin\asadmin.bat stop-domain domain1\"" start= auto DisplayName= "GFService"

Simply replace the installation paths in this command and it will create the service for you. You can see the service in the Services panel in administrative tools as GFService. Try using that service to start-stop-restart your domain and see how it works.

If you find any issues, remove the service and create this again after double checking the syntax. You can remove the service using this command:
sc delete [service name]
For me it would be:
sc delete GFService

Note here that I am using the [service name] in this command. If your display name is different then you need to use the service name. Unfortunately the Services panel only show the Display Name and you need to open the properties of that service to find out the service name. That is why just to keep things simple, I am using the same display name as the service name.

Before you use the sc command make sure you double checked all of the following or it will not work.

  • Double check if you have sc.exe in C:\Windows\System32
  • Make sure you have opened the command prompt as administrator.
  • Note the space between the parameter and value (start= auto NOT start=auto) without the space it will not work. 
  • Make sure the path to appservService.exe and asadmin.bat are correct.
  • Make sure you have all the \ s and " in the right place and with the correct spacing. 
  • This is one single command on one line, you have to type it in all at one line before you hit enter. 


If you find it difficult and for whatever reason this does not work for you, don't despair. You can also use a very simple utility created by Ryan de Laplante that will install Glassfish V2 on any windows machine.

He has give complete description on how to do it in this post that you can read for any further information. Here I am trying to further simplify how to do that.

Download the .jar file.
Place the Glassfish-as-Service.jar in the glassfish home folder

Run the following command as admin.

java -jar Glassfish-as-Service.jar -i -n [ServiceName] -d ["Glassfish home path"] -m [domain]

Example:
java -jar Glassfish-as-Service.jar -i -n Glassfish -d "c:\\software\\glassfish" -m quote

glassfishsvc v1.0 (Aug 14 2007)

Service name                : Glassfish
Glassfish installation path : c:\software\glassfish
Glassfish domain            : quote
Glassfish admin username    : admin

Installing service...
Done.

This commands can by successful Only when running command prompt as admin


Ryan have provided both the source and the jar for us. A big thank you to Ryan. He did not imposed any licensing restrictions on this work.
Download links: GlassfishSvc.jar, GlassfishSvc.java

That's it. Now you can go to the Services panel and you can start and stop the Glassfish V2 from Services panel of Windows.

For further details about this simple utility Ryan has created this Oracle wiki page for us.

Wednesday, January 5, 2011

JPA SQLServer Connection Pool using Instance Name

Creating a connection pool in Glassfish is fairly simple, as I have described in my previous post. All you need to do is to specify the URL and the Port number where the database engine is listening for the incoming connections in the JPA configuration file, i.e. sun-resources.xml.

In my previous post I used the port number of the database server instance to connect to the database. Sometimes, specially in the clustered enviournment it is not possible for you to specify the port number and you need to use the instance name to communicate with the server.

Doing that is fairly simple. All you need to do is to replace the portNumber property with the instanceName property in the configuration file. You also need to change the Database Connection URL and replae the portNumber with the instanceName. The resulting configuration will look something like this:

<jdbc-connection-pool name="MSSQL_POOL_TEST" 
                       datasource-classname="com.microsoft.sqlserver.jdbc.SQLServerDataSource" 
                       lazy-connection-enlistment="false" match-connections="false" 
                       max-pool-size="32" pool-resize-quantity="2" res-type="javax.sql.XADataSource" 
                       statement-timeout-in-seconds="-1" steady-pool-size="8"> 
         <property name="serverName" value="localhost" /> 
         <property name="instanceName" value="DBInstance" /> 
         <property name="databaseName" value="TestDB" /> 
         <property name="User" value="sa" /> 
         <property name="Password" value="5QLPWD" /> 
         <property name="URL" 
                      value="jdbc:sqlserver://localhost;instanceName=DBInstance;databaseName=TestDB" /> 
         <property name="driverClass" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" /> 
</jdbc-connection-pool>

Your connection pool is now using the instance name and as a result if the cluster management engine ever need to make any changes to the port numbers, your connection pool will not be effected by that.

Tuesday, January 4, 2011

Using Eclipselink with Glassfish

Using Eclipselink as your JPA provider is fairly simple in Glassfish V2. All you need to do to be able to create a database access object is to place the eclipse link jar files in the Glassfish library folder and create/update just two xml files, i.e. persistance.xml and sun-resources.xml. Here it how it goes.

Sample persistance.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" 
  xmlns="http://java.sun.com/xml/ns/persistence"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
            http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
  <persistence-unit name="MSSQL_POOL_TEST" transaction-type="JTA">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <jta-data-source>MSSQL_POOL_TEST</jta-data-source>
    <properties>
      <property name="eclipselink.logging.level" value="FINE" />
      <property name="eclipselink.target-server" value="SunAS9" />
    </properties>
  </persistence-unit>
</persistence>

This is a very simple file containing only one persistance unit. The persistance unit name MSSQL_POOL_TEST is the JNDI name of the connection pool that the persistance provider will use. The actual connection pool is defined in the sun-resources.xml file. The transaction type I am using here is default JPA transaction.

Sample sun-resources.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE resources PUBLIC 
"-//Sun Microsystems, Inc.//DTD Application Server 9.0 Resource Definitions //EN"
      "http://www.sun.com/software/appserver/dtds/sun-resources_1_3.dtd">
<resources>
    <jdbc-resource enabled="true" jndi-name="MSSQL_POOL_TEST"
               object-type="user" pool-name="MSSQL_POOL_TEST" />
    <jdbc-connection-pool name="MSSQL_POOL_TEST"
        allow-non-component-callers="false" associate-with-thread="false"
        connection-creation-retry-attempts="0"
        connection-creation-retry-interval-in-seconds="10"
        connection-leak-reclaim="false" connection-leak-timeout-in-seconds="0"
        connection-validation-method="auto-commit"
        datasource-classname="com.microsoft.sqlserver.jdbc.SQLServerDataSource"
        fail-all-connections="false" idle-timeout-in-seconds="300"
        is-connection-validation-required="true"
        is-isolation-level-guaranteed="true" lazy-connection-association="false"
        lazy-connection-enlistment="false" match-connections="false"
        max-connection-usage-count="0" max-pool-size="32"
        max-wait-time-in-millis="60000" non-transactional-connections="true"
        pool-resize-quantity="2" res-type="javax.sql.XADataSource"
        statement-timeout-in-seconds="-1" steady-pool-size="8"
        validate-atmost-once-period-in-seconds="0" wrap-jdbc-objects="false">
        <property name="serverName" value="localhost" />
        <property name="portNumber" value="28150" />
        <property name="databaseName" value="TestDB" />
        <property name="User" value="sa" />
        <property name="Password" value="5QLPWD" />
        <property name="URL"
                value="jdbc:sqlserver://localhost:28150;databaseName=TestDB" />
        <property name="driverClass" 
                value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
    </jdbc-connection-pool>
</resources>

That's it....

Your SQLServer Connection Pool is now created with a persistance context. All you need now is the jar files for the database drivers and eclipse link in the Glassfish lib folder or any other location in your classpath. I am referring to the Glassfish lib folder only because of ease of use when you try it yourself for the first time.

Most of the properties of the connection pool are selfexplanatory, however, I will try to provide further explanation of all of these properties in a saparate post sometime.