Thursday, May 31, 2012

Fix for PortletGrailsPlugin for Grails 2.x


 Problem:


Using the Grails Portlet plugin version 0.9.1 within a Grails 2.0.0 environment I get the following error:

Caused by MissingMethodException: No signature of method: org.codehaus.groovy.grails.plugins.web.ControllersGrailsPlugin.registerControllerMethods()

 Solution:

 We get this problem because in the lastet version of Grails 2.x, the "registerControllerMethods()" method no longer exists, and nobody is currently maintaining the plugin at the moment. But I've been working hard to find a solution so here it is.


In the PortletsGrailsPlugin.groovy file change the following from:


         def controllersPlugin = new ControllersGrailsPlugin()
         controllersPlugin.registerControllerMethods(mc, ctx)


To this:
         def enhancer = new MetaClassEnhancer()
         enhancer.addApi(new ControllersApi(getManager()))
         enhancer.enhance mc

Wednesday, May 30, 2012

Grails groovy.lang.MissingPropertyException: No such property: portletResponse

Problem:

Using the Grails Porlet plugin, I submitted an action request which would in turn invoke the actionView method of the generated portlet. However I received the following error, when I try to use the auto injected variable 'portletResponse':

groovy.lang.MissingPropertyException: No such property: portletResponse

Discussion:


I decided to dump out all the attributes for the request object as follows:

    def actionView = {
        logger.info("actionView")
        
        
        for (String attrName : request.getAttributeNames()) {
            logger.info("Name="+attrName+"    Value="+request.getAttribute(attrName))
        }
        portletResponse.setRenderParameter("prp-1", "value-1"); // <-- portletResponse is supposed to be auto injected
    }

Then when I viewed the output I saw the following in the logs:

2012-05-30 23:48:28,703 [http-bio-8080-exec-104] INFO  portal.ApfPortlet  - Name=javax.servlet.include.request_uri    Value=/apf-portal/Apf/invoke
2012-05-30 23:48:28,703 [http-bio-8080-exec-104] INFO  portal.ApfPortlet  - Name=javax.servlet.include.context_path    Value=/apf-portal
2012-05-30 23:48:28,704 [http-bio-8080-exec-104] INFO  portal.ApfPortlet  - Name=javax.servlet.include.servlet_path    Value=/Apf
2012-05-30 23:48:28,704 [http-bio-8080-exec-104] INFO  portal.ApfPortlet  - Name=javax.servlet.include.path_info    Value=/invoke
2012-05-30 23:48:28,704 [http-bio-8080-exec-104] INFO  portal.ApfPortlet  - Name=com.liferay.portal.kernel.servlet.PortletServletConfig    Value=org.apache.catalina.core.StandardWrapperFacade@19a5b51
2012-05-30 23:48:28,704 [http-bio-8080-exec-104] INFO  portal.ApfPortlet  - Name=grails.portlet.name    Value=Apf
2012-05-30 23:48:28,705 [http-bio-8080-exec-104] INFO  portal.ApfPortlet  - Name=grails.portlet.config    Value=com.liferay.portlet.PortletConfigImpl@1647724
2012-05-30 23:48:28,707 [http-bio-8080-exec-104] INFO  portal.ApfPortlet  - Name=javax.portlet.config    Value=com.liferay.portlet.PortletConfigImpl@1647724
2012-05-30 23:48:28,708 [http-bio-8080-exec-104] INFO  portal.ApfPortlet  - Name=com.liferay.portal.kernel.servlet.PortletServletResponse    Value=com.liferay.portal.kernel.servlet.StringServletResponse@faa1b4
2012-05-30 23:48:28,708 [http-bio-8080-exec-104] INFO  portal.ApfPortlet  - Name=INVOKER_FILTER_URI    Value=/Apf/invoke
2012-05-30 23:48:28,717 [http-bio-8080-exec-104] INFO  portal.ApfPortlet  - Name=javax.portlet.response    Value=com.liferay.portlet.ActionResponseImpl@13a1d01
2012-05-30 23:48:28,718 [http-bio-8080-exec-104] INFO  portal.ApfPortlet  - Name=PORTLET_ID    Value=Apf_WAR_apfportal
2012-05-30 23:48:28,730 [http-bio-8080-exec-104] INFO  portal.ApfPortlet  - Name=com.liferay.portal.kernel.servlet.PortletServletRequest    Value=com.liferay.portal.servlet.NamespaceServletRequest@3858a8
2012-05-30 23:48:28,731 [http-bio-8080-exec-104] INFO  portal.ApfPortlet  - Name=javax.portlet.portlet    Value=org.codehaus.grails.portlets.GrailsDispatcherPortlet@9a5b5c
2012-05-30 23:48:28,740 [http-bio-8080-exec-104] INFO  portal.ApfPortlet  - Name=WINDOW_STATE    Value=normal
2012-05-30 23:48:28,740 [http-bio-8080-exec-104] INFO  portal.ApfPortlet  - Name=org.codehaus.groovy.grails.WEB_REQUEST    Value=ServletWebRequest: uri=/c/portal/layout;client=127.0.0.1;session=ED170D76D6BB5AF372ED336B020604E5;user=2
2012-05-30 23:48:28,754 [http-bio-8080-exec-104] INFO  portal.ApfPortlet  - Name=javax.portlet.lifecycle_phase    Value=ACTION_PHASE
2012-05-30 23:48:28,754 [http-bio-8080-exec-104] INFO  portal.ApfPortlet  - Name=javax.portlet.request    Value=com.liferay.portlet.ActionRequestImpl@14480c8
2012-05-30 23:48:28,761 [http-bio-8080-exec-104] INFO  portal.ApfPortlet  - Name=com.liferay.portal.kernel.servlet.PortletServletFilterChain    Value=com.liferay.portlet.FilterChainImpl@62fa4e

As you can see, the attributes highlighted in red can give you access to the portletRequest and portletResponse objects.

Solution:

After dumping out the attributes you can now get the PortletRequest and PortletResponse as follows:


        PortletResponse portletResponse = request.getAttribute("javax.portlet.response")
        PortletRequest portletRequest = request.getAttribute("javax.portlet.request")


grails portlet plugin actionView not invoked

Problem:


I was using the Grails plugin for creating Portlets found here: http://grails.org/plugin/portlets

I created the Portlet code by invoking the following command: 
grails create-portlet MyFirst

This automatically created the Portlet class which contains the following code snippet:


    def actionView = {
        //TODO Define action phase for 'view' portlet mode
        portletResponse.setRenderParameter("prp-1", "value-1");
    }

The following the instructions as documented, I invoke the following command to generate the view for the portlet:

grails generate-portlet-views com.company.MyFirst
It creates several files with one of them being the view.gsp file. This file has a snippet as shown:


<form action="${portletResponse.createActionURL()}">
    <input type="submit" value="Submit"/>
</form>


The trouble was, when I goto submit the form, the actionView method never gets invoked. Only the renderView method get's invoked:

Solution 

The problem was that the form did not declare a POST method. I modified the view.gsp as follows:


<form action="${portletResponse.createActionURL()}" method="post">
    <input type="submit" value="Submit"/>
</form>

Reference:

 

Tuesday, May 29, 2012

Native SQL query using Hibernate causes ArrayIndexOutOfBounds

Problem:


In hibernate I was trying to use a native SQL query to retrieve records from the database when I encountered an ArrayIndexOutOfBoundsException on the following piece of code:


                String sql = "SELECT * FROM fcs f"
                SQLQuery query = session.createSQLQuery(sql)                
                //query.setString(0, barcode.toString())
                try {
                    list = query.list()   // <-- ERROR HERE
                } catch(Exception e) {
                    //e.printStackTrace()
                    logger.error(e)
                    ByteArrayOutputStream baos = new ByteArrayOutputStream()
                    PrintWriter pw = new PrintWriter(baos)
                    e.printStackTrace(pw)
                    pw.close()
                    byte[] array = baos.toByteArray()
                    String exp = new String(array)
                    logger.error(exp)
                }

As you can see, I managed to dump out the stacktrace which looked as follows:


Caused by: java.lang.ArrayIndexOutOfBoundsException: 0
   at org.hibernate.type.TypeHelper.disassemble(TypeHelper.java:146)
   at org.hibernate.cache.StandardQueryCache.put(StandardQueryCache.java:106)

The important thing to notice about this stacktrace is that the error happens out of the StandardQueryCache.

Solution:


In grails, by default the standard query cache was enabled. To workaround the issue, I've disable it in the DataSource.groovy file as follows:


hibernate {
    cache.use_second_level_cache = false
    cache.use_query_cache = false
    cache.region.factory_class = 'net.sf.ehcache.hibernate.EhCacheRegionFactory'
}

References:


Grails Value '0000-00-00 00:00:00' can not be represented as java.sql.Timestamp

Problem: 

When using mySQL Hibernate to convert a database value to a Timestamp I get the following error:

Value '0000-00-00 00:00:00' can not be represented as java.sql.Timestamp

 Solution:

 append the zeroDateTimeBehaviour=convertToNull parameter to end of the URL configuration as follows:

jdbc:mysql://localhost:3306/facs?zeroDateTimeBehavior=convertToNull

References:


Thursday, May 24, 2012

Grails data binding does not work on injected methods

Problem:

For Grails projects, you can use inject whole method definitions in the BootStrap.groovy file.

However, there is a drawback to method injection:

Grails will not be able to perform data binding on an injected method

 For example if we define the following method in BootStrap.groovy:

Bootstrap.groovy
domainClass.metaClass.getAttributeMap = {
   return new Map()
}

And then we our GSP file:

GSP file
<g:textField name="attributeMap[123].value" />

Grails will not be able to bind the value of the input element in the GSP defined by "attributeMap[123].value", to the domain object through the injected method getAttributeMap() .

Workaround:

Method injection has a lot of advantages and it would be a shame if you had to give it up simply because data binding could not work. Oneway around this problem, is to define a concrete method that will internally invoke the injected method.

For example,


     public Map<String, Attribute> getAttributeMapForDataBinding() { // <--- Define concrete method
         return this.getAttributeMap() // <--- Invoke the injected method
     }

Then in your GSP you can have:
<g:textField name="attributeMapForDataBinding[123].value" />

Sunday, May 13, 2012

Spring STS plugin manager issue

Problem: The Plugin Manager window does not appear

I am using Spring STS 2.9.1 when I encountered an issue where the Plugin Manager was refusing to show up

Discussion:

My first instinct was to try a newest release of Spring STS which at the time was 3.0.0.M1
I downloaded and installed it, and was able to successfully open the plugins manager. YAY!
At first, I thought I was finished and ready to continue coding. Then when I went to open up a file, just about any file, I get a NullPointerException. I realized this version had it's own set up problems, that I was not ready to deal with.

I returned back to version 2.9.1 and found a way to patch it up. The solution is below:

Solution:


I managed to find a patch with a fix to the "Grails support" extension from a nightly build. To do this, in the STS menu select:

Window -> Preferences -> Install/Update-> Available software sites


Under "Available software sites" add the following sites:
  1. http://dist.springsource.com/snapshot/TOOLS/nightly/e3.7
  2. http://download.eclipse.org/mylyn/snapshots/3.7/
 Then click "Ok" and close the window.


 To activate the update process do the following:

Help -> Check for Updates

Follow the instructions to perform the update and restart STS.

And your good to go!

References:


Liferay LDAP com.liferay.portal.UserScreenNameException

I was attempting to configure Liferay to use LDAP.

After configuration was complete, I attempted to login using my LDAP credentials and I encountered this error:


com.liferay.portal.UserScreenNameException
I looked around for answers and it appears that the "Screen name" parameter is sensitive to space characters and underscores as mentioned in this forum:

http://www.liferay.com/community/forums/-/message_boards/message/5681334

So I switched the "Screen name" value from "cn" to "uid", and this resolved the issue