Showing posts with label Grails. Show all posts
Showing posts with label Grails. Show all posts

Saturday, June 23, 2012

Grails JSF 2 plugin with OpenFaces

Now that I have got Icefaces 3 working with the Grails JSF 2 plugin, I am now trying OpenFaces from www.openfaces.org. Since the plugin is compatible with JSF 2.0, I will be using the OpenFaces 3.0 libraries rather than the 2.0 libraries.

To start, you need to create the grails application (grails create-app) and install the JSF 2 plugin (grails install-plugin jsf2). You will also need to install the templates to modify the web.xml file (grails install-templates). Refer to my previous posts on examples of these steps.

For OpenFaces, you will need to copy these libraries into the lib directory:
  • openfaces.jar
  • cssparser.jar
  • jcommon.jar
  • jfreechart.jar
  • sac.jar

All these files can be found in the openfaces-3.0.zip file, which you can download from the OpenFaces website.

You will also need to make just one change to the web.xml file which is to add the following lines:

<context-param>
<param-name>org.openfaces.validation.clientValidation</param-name>
<param-value>onSubmit</param-value>
</context-param>

That's all that is needed. You can now start creating your OpenFaces app, using xhtml as the extension for the JSF files. You can use the grails create-bean command to create the backing bean for the JSF files.

UPDATE:
There are limitations with the above configuration.  The openfaces.jar library uses Class.forName to resolve some of the classes to unpack (deserialize) the objects.  However, if the classes are defined in the src directory which Grails allows for Dynamic Reloading, then it is NOT available to the jar file class loader (i.e the root classloader). Hence this results in a ClassNotFoundException. This problem occurs when using the run-app (which allows Dynamic Reloading) command.

I tried to unpack the source for the Openfaces components into the src/java directory and include 2 additional jars (portlet api and org.jboss.el).  This then allows the user-defined classes in src to be found since all of the source is dynamic, BUT the faces file parser now does not resolve the namespace for the Openfaces component.  So this is a dead-end.

Alternatively, if you don't need dynamic reloading, you can run the grails app by using run-war command instead.  This will compile all the sources and make it all available to the classloader.  However, there is problem running JSF2 plugin using run-war.  The GrailsResourceResolver.java resolver provided by the JSF2 plugin cannot work in run-war environment as it expects to look for the Grails GSP files like in the development environment instead of the war environment.  If you don't need to use the GSP files, you can make a copy of this file (from jsf2 plugin source directory and put into your project's src/java directory (keeping all the directory paths the same).  Then edit the file and remove all references and code calling the "resourceLoader" member.   Then then allows the run-war to work and you can now run your .xhtml files with the Openfaces components.

Icefaces 3 on Grails with JSF 2 Plugin

Continuing on the previous posts, I have managed to get the new Icefaces 3 libraries working with the Grails JSF 2 Plugin.

To get it working, just follow all the steps in the previous post for Icefaces 2.0.2. For Icefaces 3, download the libraries and replace the all the Icefaces jars on the lib directory with these files from Icefaces 3:
icefaces.jar
icefaces-ace.jar
icefaces-compat.jar
icepush.jar

However, there is one additional change that needs to be made to the web.xml file. Please add the following lines to the web.xml template file:

<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>false</param-value>
</context-param>

If you don't add these lines, when you click on a button (or do a post back), there a Server Error popup will appear and on the console, the system will raise a Java exception as follows:

java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to com.sun.faces.application.view.StateHolderSaver

Please try it and let me know if all the Icefaces 3 features are working with this Grails JSF2 plugin. By the way, this has been tried on Grails 1.3.7.

Saturday, November 5, 2011

Icefaces 2.0.2 with Grails

I finally managed to get Icefaces 2.0.2 to run with Grails. The steps are as follows:

1) Create a new grails application:
grails create-app myapp
cd myapp

2) Install the jsf2 plugin:
grails install-plugin jsf2

3) Install the templates to edit the web.xml file:
grails install-templates

4) Copy the following JARs into the lib directory:
icefaces-2.0.2.jar
icefaces-ace-2.0.2.jar
icefaces-compat-2.0.2.jar
icepush.jar

5) Add the following lines into the web.xml template in src/templates/war:
<servlet>
<servlet-name>Resource Servlet</servlet-name>
<servlet-class>com.icesoft.faces.webapp.CompatResourceServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>Resource Servlet</servlet-name>
<url-pattern>/xmlhttp/*</url-pattern>
</servlet-mapping>

<context-param>
<param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
<param-value>true</param-value>
</context-param>

<context-param>
<param-name>javax.faces.VALIDATE_EMPTY_FIELDS</param-name>
<param-value>false</param-value>
</context-param>

And that's it. You can now create JSF files with the extension .xhtml in
the grails-app/view directory (following the JSF2 format).

Sunday, September 18, 2011

Oracle OrdAudio and Grails

Recently I have started prototyping some web applications on Grails that uses the Oracle interMedia capabilities. One of the key problems is that you cannot use GORM to define a property which is an Oracle OrdMedia component, such as OrdAudio. I needed a way to stream out the audio data stored in this field in an Oracle database for which I created a Controller in Grails. But how do you retrieve the field object ?

Firstly I used Groovy SQL to get hold of the field by doing the following:

import groovy.sql.Sql

class StreamingController {
def sessionFactory

def index = {
String sqlstr = "select audio_file table where id = ?"
Sql sql = new Sql(sessionFactory.currentSession.connection())
sql.eachRow(sqlstr,[params.id]) { row ->
println row[0]
}
}
}

Invoking the "streaming" url, Grails report that the row[0] is a oracle.sql.STRUCT object. So how do I convert that into an OrdAudio object ?

Turns out that Oracle uses a Factory to build the OrdAudio object from the STRUCT.

sql.eachRow(sqlstr,[params.id]) { row ->
oracle.sql.STRUCT str = row[0]
oracle.sql.CustomDatumFactory factory = oracle.ord.im.OrdAudio.getFactory()
oracle.ord.im.OrdAudio audio = factory.create(str, java.sql.Types.STRUCT)
...
}

So you now have the OrdAudio object for which you can check its properties or extract the audio data out. If the data is stored in the BLOB, then you will use:

InputStream inp = audio.getDataInStream()

If the data is stored in a BFILE, then you will use:

oracle.sql.BFILE bfile = audio.getBFILE()
bfile.open()
InputStream inp = bfile.getBinaryStream()

You can then stream the data into the "response.outputStream" using the write method.