Sonntag Jan 31, 2010

Eclipse Galileo - JSF Content Assist for xhtml files

In the past I wrote some articles about how to configure Eclipse to get a content assistance for xhtml files in a jee project (things like code completion and mouse over hints). (see: Ganymede and faclets and Eclipse JSF/Facelet Support)

As Thiago dos Santos Prado posted in one of the comments all the stuff of configuration seems to be dispensable in Eclipse Galileo. But still Eclipse Galileo is not disposed to support content assistance for xhtml file out of the box. I can't find out why Eclipse ignores xhtml files in most jee projects as this is a standard file format for JSF applications. Maybe that the problem only exists for Maven based projects as maven is a little bit untended in Eclipse IDE. 

But it seems to be now very easy to add this missing feature simply by adding an additional content type for xhtml files:

  1.  Open "window" > "Preferences..." and select "General" > "Content Types"

     

  2. Next click the button "Add..." button and add the new content type ".xhtml"

     

  3. Finally check if the File Association for .xhtml Files is set to "JSP Editor". In my case this is already configured right.




Thats it!

Now you have content assistence for Java Server Faces and also all included JSF third libraries like RichFaces or MyFaces.

 

Freitag Aug 14, 2009

RichFaces - SuggestionBox and hidden Field

Today I was faced with a problem implementing a suggestionbox in my JSF web application using RichFaces. There are a lots of examples and well documented api in the RichFaces Developer Guide. But my problem was that the seach phrase the user types into the input field was only for searching in the backend. After the user select one entry form the suggegstion box I need to set an internal key into a  property of my BackingBean. But this key should not be shown to the user. So the typical examples did not work for me:

<h:inputText value="#{bean.property}" id="suggest"/>
<rich:suggestionbox for="suggest" suggestionAction="#{bean.autocomplete}"  var="suggest">
        <h:column>
                <h:outputText value="#{suggest.text}"/>
        </h:column>
</rich:suggestionbox>

The solution for me was to left the value binding of the input component. Instead of that I use the f:setPropertyActionListener to update my backing bean property. So I was able to display user-friendly values from my backend. After user select one entry I store the key of that entry into my backing bean.

<h:inputText id="suggest_input" />
   <rich:suggestionbox for="suggest_input" minChars="1"
       fetchValue="" nothingLabel="no entry found"
        suggestionAction="#{myMB.suggestData}" var="suggest">
        <h:column>
            <h:outputText value="#{suggest.firstname}" />
        </h:column>
         <h:column>
            <h:outputText value="#{suggest.lastname}" />
         </h:column>
            <a4j:support ajaxSingle="true" event="onselect"
                action="#{myMB.refreshData}" reRender="data_id">
            <f:setPropertyActionListener value="#{suggest.userID}"
                    target="#{myMB.userID}" />
         </a4j:support>
  </rich:suggestionbox> 

myMB is my BackingBean which processes the SQL Data lookup with the method "suggestData". The user enters first or last name and my suggestData method did a SQL search using some LIKE statements.

    public ArrayList<UserData> suggestData(Object event)
            throws SQLException {
        ArrayList<UserData> list = new ArrayList<UserData>();
        String sPref = event.toString();
        int iPref = -1;

        sQuery = "SELECT patID,firstname,lastname FROM userlist "
                + " WHERE firstname LIKE '"
                + sPref
                + "%' OR lastname LIKE '"
                + sPref
                + "%' "
                + " ORDER BY lastname ASC";
.....
........

The BackingBean holds also the userID which is an internal primary key. But the suggestData method returns an Array of userData containing the First, Last and userID. But the userid is not displayed in the suggestionbox. When the user selects an entry the a4j:support Ajax Action is triggerd whid did some rerendering (but this is not the trick). The trick is to use the f:setPropertyActionListner to update the userID property form my backing bean myMB. The inputText component is not bound to any value of my backing beans. So this is a simple search input field.

Maybe this example could be useful for someone.

Samstag Mai 23, 2009

Eclipse JSF/Faclet Support in a Maven Web Project

In the following section I will describe how to configure a Maven Web Module in Eclipse Ganymede to get full support of Content assist, Hover Help and code completion for JSF and Facelets.

These features are supported by the Eclipse Web Tool Platform (WTP). So it seams not to be so difficult to configure a existing web project. But as Maven have some different in building a classpath and updating project configuration in Eclipse you need to be careful to reconfigure a Maven project. I spent a lot of time to find out why it sometimes did not work. So I hope my following walk-through will be helpful to you.

The Situation:

I have an existing Maven Web Project which I checked out from a code repository into my eclipse workspace. Therefor I used the Maven Plugin and the Maven SVN Integration Plugin.

The Maven Project I am working with is a JEE Web module with JSF and Faclets support and also uses the JBoss RichFaces JSF components.So the goal is to get content assist when editing a .xhtml faclets file in my web project.

The Facelets Plugin

To get things run I need first to install the faclets plugin for eclipse.  The reason for adding this plugin is that a faclets application typical uses .xhtml pages to represent the jsf resources. The Eclipse WTP did not support .xhml files per deault so the faclets plugin will add the JSF features to also .xhtml files. Additional the plugin includes some wizzards and a new WTP Facete.

You can download the plugin from here. Extract the file and copy the jars into your /plugin folder of your Eclipse Ganymede. Next restart Eclipse!

Adding a JSF Implementation and Server Runntime

Next step is to add a JSF Implementation into you Eclipse Workspace. You can use any Implementation. I take the JSF Implementation form my Glassfish server.  There is a Blog where  Cay Horstmann explains the details:
http://weblogs.java.net/blog/cayhorstmann/archive/2007/07/jsf_support_in.html

So open the Eclipse preferences dialog and go to Web->JavaServer Faces->Libraries.

Create a new JSF library and name the library "GlassfishJSF-impl". Add only the jsf-impl.jar file. This file is located in the /glassfish/lib folder from your glassfish installation.



Important: Make sure that the option "is JSF Implementation" is checked!

Next add the Server Runtime. Select the Server Node and add your JEE Server (in my case glassfish)

 

Now Restart you Eclipse!

Add the Server and JSF Libraries to the Java Build Path

Next check the "Java Build Path" settings of your Web Project. You need now to add two libraries to your project.

The Server Runtime Library of Glassfish and the JSF Implementation which added before to the workspace environment.

Click "Add Library..." and select "Server Runtime"

 

Choose the Glassfish Server from the Server Runtime list. Click finish.

Next I add the JSF Library created before. So click again "Add library..." and add a JSF Library and select you GlassfishJSF-Impl created before:

 

Finally your project library settings should look like this

Add the JSF and Faclets Facets

Next you need to add the Project Facets for JSF 1.2 support and Facelet 1.0. A Facet is a WTP specific feature which adds additional tools and features to a web project. The Facelet 1.0 Facete is an additional feature added by the Facelet plugin I added before.

To add a new Facete you open the preference dialog for your web project and select the "Project facets" node.

If this Node is not present in you project preferences Eclipse has not recognized your Maven web project as a Eclipse Web Project. So you need first to add the WTP Nature to your project manually.

  1. Switch in the "Navigator" View
  2. open the file ".project"
  3. add the nature
      <nature>org.eclipse.wst.common.project.facet.core.nature</nature>
  4. save the .project file

Now you can add the different facets in the following order:

  1. Select Java 5.0
  2. Select Dynamic Web Module 2.5
    after that you can see the link "Further configuration available" - open the dialog




    As I am working in a maven project I change the Content and Java Source Directory into
    /src/main/webapp
    /src/main/java
    which are the default maven source folders
    Also I unchecked the "Generate deployment descriptor" as my maven project still have the necessary descriptors.




  3. Next Select "JavaServerFaces 1.2".
    Again there is "Further configuration required"
    You can select the option "Server Supplied JSF Implementation"



    Choose the "Next" Button to switch through the different config pages.

  4. Finally add the "Facelet 1.0 " support.
    Again there is "Further configuration available"



    I disabled all options as my maven project is well configured

  5. Finally restart eclipse

Now you should have the content assist and hover help in your xhtml files.
Eclipse is parsing all necessary libraries so also my RichFaces tags are now known by Eclipse!

The first time you get the content assist from Eclipse it will take some time as Eclipse needs to analyze the tag libraries. 


If it did not work...

In some cases this did not work. Then the main reason seams to be that the Eclipse java build classpath is not well configured. Check the Java Build Path settings. Remove and add some Libraries - this will help Eclipse to update the Workspace settings and restart Eclipse. Also wait some time after restart until Eclipse have finished all inizalizing.

Dienstag Mai 19, 2009

Escape Problem downloading Files form a Web / JSF Application

Today I stumbled into a problem with my JSF Web Application supporting File Upload/Download Functionality.

Everything works fine until some user uploaded files with "blank" in the filename e.g. "my fantastic long filename.doc" or files with german characters like "große datei mit wörtern.doc"

The Upload of sees files is no problem for my JSF up. But if a user tries to download such a file an error 404 occurs.

My JSF Implementation supports a typical form to download the files from a file list. It looks like this:

 <h2>Download</h2>

<c:forEach var="attachment" items="#{workitemLobBean.files}">
<h:outputLink target="_blank"
value="#{facesContext.externalContext.requestContextPath}/Service/$file/#{attachment}">
<h:outputText value="#{attachment}" />
</h:outputLink>
<br />
</c:forEach>

So the filenames will be escaped into something like :

"my+fantastic+long+filename.doc"

which leads into the error 404. To avoid this escaping I used the following trick (not very nice but it works)

 <h2>Download</h2>

<c:forEach var="attachment" items="#{workitemLobBean.files}">
<h:outputText escape="false" value="&lt;a target='_balnk' href='" />
<h:outputText escape="false" value="#{facesContext.externalContext.requestContextPath}/Service/$file/#{attachment}" />
<h:outputText escape="false" value="'&gt;#{attachment}&lt;/a&gt;" />

<br />
</c:forEach>

If you find a better solution to escape filenems in JSF output let me know.

Sonntag Sep 21, 2008

RichFaces - using custom Skinns

The current Version of RichFaces (3.2.1.GA) allows you to use skins in your web application in a much easier way as in the RichFaces versions before.

A detailed documentation about this feature can be found here:

http://www.jboss.org/file-access/default/members/jbossrichfaces/freezone/docs/devguide/en/html/ArchitectureOverview.html#Skinnability

I used this in my own web application and did only two things:

1.) I created a custom skin property file. "myfirstskin.skin.properties" and placed this file into the /src/main/resources folder of my maven project (if you did not use maven put this file in the /META-INF/skins folder or classpath of your webapp)

You can also copy a existing skin property file to start. You will find skins form RichFaces in the richfaces-impl-3.2.1.GA.jar file under /META-INF/skins/.

This is a example for a skin.propertyfile (blueSky.skin.properties)

#Colors

headerBackgroundColor=#BED6F8
headerGradientColor=#F2F7FF
headerTextColor=#000000
headerWeightFont=bold
generalBackgroundColor=#FFFFFF
generalTextColor=#000000
generalSizeFont=11px
generalFamilyFont=Arial, Verdana, sans-serif

controlTextColor=#000000
controlBackgroundColor=#ffffff
additionalBackgroundColor=#ECF4FE

shadowBackgroundColor=#000000
shadowOpacity=1
panelBorderColor=#BED6F8
subBorderColor=#ffffff

tabBackgroundColor=#C6DEFF
tabDisabledTextColor=#8DB7F3

trimColor=#D6E6FB
tipBackgroundColor=#FAE6B0
tipBorderColor=#E5973E
selectControlColor=#E79A00

generalLinkColor=#0078D0
hoverLinkColor=#0090FF
visitedLinkColor=#0090FF

# Fonts
headerSizeFont=11px

headerFamilyFont=Arial, Verdana, sans-serif
tabSizeFont=11
tabFamilyFont=Arial, Verdana, sans-serif
buttonSizeFont=11
buttonFamilyFont=Arial, Verdana, sans-serif
tableBackgroundColor=#FFFFFF
tableFooterBackgroundColor=#cccccc
tableSubfooterBackgroundColor=#f1f1f1
tableBorderColor=#C0C0C0
tableBorderWidth=1px

#Calendar colors
calendarWeekBackgroundColor=#F5F5F5
calendarHolidaysBackgroundColor=#FFEBDA
calendarHolidaysTextColor=#FF7800
calendarCurrentBackgroundColor=#FF7800
calendarCurrentTextColor=#FFEBDA
calendarSpecBackgroundColor=#E4F5E2
calendarSpecTextColor=#000000

warningColor=#FFE6E6
warningBackgroundColor=#FF0000
editorBackgroundColor=#F1F1F1
editBackgroundColor=#FEFFDA

#Gradients
gradientType=plain

2.) next I added two params into my web.xml file:

	<!-- ### Richt Faces params deepMarine #### -->
<context-param>
<param-name>org.richfaces.SKIN</param-name>
<param-value>deepMarine</param-value>
</context-param>

<context-param>
<param-name>org.richfaces.CONTROL_SKINNING</param-name>
<param-value>enable</param-value>
</context-param>

 The first param tells RichFaces to use a predefined or custom skin property file (the name is the first part of your .skin.property file)

And the second param (very important) tells RichFaces also to render standard HTML tags in this skin.

So if you use a standard JSF Tag like

	<h:outputLabel value="User name:" />
<h:inputText id="j_username" />

<h:outputLabel value="Password:" />
<h:inputSecret id="j_password" />
 

these tags will also be renderd in new cool style!

Donnerstag Sep 18, 2008

RichFaces & Maven - easy setup!

The last days I read a lot about RichFaces and saw this cool live demo. RichFaces sparks my interest. As the JSF Framework RichFaces from JBoss supports much more components as other frameworks and also really cool Ajax features, I started to build my first jee web module using RichFaces.
First I read this quick guide which shows how to build a JEE Webmodul using RichFaces in general. But as I planed to integrate my first example into an existing JEE project build on maven I search a lot to find out how to setup a Maven Web module with RichFaces Support.

Here is my personal quick guide to setup a maven web app with RichFaces:

1.) Add the JBoss Maven repository to your Maven Installation:

first you need to add the following repository description into your setup.xml file located in your Maven root directory:

 	<!-- JBoss RichFaces Repository -->
<repository>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
<updatePolicy>never</updatePolicy>
</snapshots>
<id>repository.jboss.com</id>
<name>Jboss Repository for Maven</name>
<url>
http://repository.jboss.com/maven2/
</url>
<layout>default</layout>
</repository>
</repositories>

So later maven will be able to download the necessary components. (I don't know why this framework is not included into the standard maven repository)

2.) Add the RichFaces Dependencies

the next (and final) step is to add the RichFaces Dependencies into your Maven Web Module (I assume that you know how to build a web module with maven).
To find out the right dependencies takes me the most time as I did not found an example on the JBoss RichFaces Homepage. But finally I found these dependency configuration which works fine:

   <dependencies>
<dependency>
<groupId>org.richfaces.ui</groupId>
<artifactId>richfaces-ui</artifactId>
<version>3.2.1.GA</version>
</dependency>
</dependencies>

So add these three dependencies into your pom.xml.

That's really all!

I completed my first integration test with the Simple Ajax Echo example at it works perfect !

Now I begin to love RichFaces :-)

Sonntag Jun 22, 2008

Eclipse - JavaServer Faces - Configuration

In some cases it can happen that your Eclipse Web Project did not support code completion in a JSP or JSF page.
This happens to me in a JSF Project with MyFaces and Facelets Support. I build up the project using Maven so the project build was sucessfull and the project works well on my server but typing code with Eclipse JSP Editor war extreamly annoying as Eclipse did not support my with code completion.

The reason was that the project facets for my project where broken and also MyFaces Support was not added to Eclipse correctly. Indeed it is necessary to configure the myfaces support in Eclipse manually and I am not sure if I was not intelligent enough or the Eclipse WTP is not so easy to use as I should be.

So follow these steps if you run into a similar problem  :

  1. create a MyFaces Folder localy on your computer (e.g: /home/user/myfaces)
  2. move the MyFaces libs and tomahawk libs into a subfolder lib/ (e.g:/home/user/myfaces/lib)
    • commons-beanutils-x.x.x.jar
    • commons-codec-x.x.x.jar
    • commons-collections-x.x.jar
    • commons-digester-x.x.jar
    • commons-discovery-x.x.jar
    • commons-logging-x.x.x.jar
    • myfaces-api-x.x.x.jar
    • myfaces-impl-x.x.x.jar
    • tomahawk-x.x.x.jar
  3. move the tld Files for myfaces and tomahawk in a /tlds subfolder (e.g./home/user/myfaces/tlds)
    • myfaces-impl-x.x.x-tlddoc.jar
    • tomahawk-x.x.x-tlddoc.jar
  4. Edit the JavaServer Faces LIbraries
    1. open Window->Preferences
    2. go to Web and XML > JavaServer Faces Tools > Libraries
    3. add a new library "MyFaces" with all the jar files moved before to your myfaces/lib folder
    4. add a new library "MyFacesTLD" with all the jar files moved before to myfaces/tlds folder
  5. Next edit the Project Facets of your Web Project (Select your project and open >Project Properties  > click modify )
    1. if there is allready available a JavaServerFaces Support - remove JavaServerFaces 1.2
    2. add JavaServerFaces 1.2. support and press "next" button
    3. select option "Sever supplied JSF Implemenation" and add the component libraries configured before in the right part of the selection. This is the importend part! And I did not found this dialog after clicking on "finish"

 After this stepps code competion works for my JSF Project. Notice that I work with maven and Maven integration in Eclipse is currently not the best. But maybe this instruction will help you...

Mittwoch Jun 18, 2008

Form based authentification using Facelets

Yesterday I found out how to configure my JEE Web Application with form-based login. In general it is not difficulty to secure a JEE Web Application with form based login. This is explained on lot of websites like this one: http://www.developinjava.com/readarticle.php?article_id=6

The problem I stumbled into was that my Web Application uses the facelets framework. So I have a lot of general layout parts like css and images which I wanted to use also in my Login Form and also some help pages which should be accessible without authentification.

To divide the web application into a restricted and a public area (where no authentification is needed) is easy:

in the web.xml you can specify the secured JSP pages separated in a folder e.g:

 <security-constraint>
    <web-resource-collection>
      <web-resource-name>restricted</web-resource-name>
      <url-pattern>/faces/pages/*</url-pattern>
       <http-method>GET</http-method>
      <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
      <role-name>org.imixs.ACCESSLEVEL.AUTHORACCESS</role-name>
    </auth-constraint>
  </security-constraint>

The Login.xhtml which I placed outside my secured /pages folder makes use of facelets technology and looks as followed:

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:z="http://www.qualcomm.com/jsf/core"
    xmlns:c="http://java.sun.com/jstl/core"
    xmlns:fn="http://java.sun.com/jsp/jstl/functions">

<ui:composition template="/layout/layout.xhtml">
    <ui:define name="content">
        <form
            method="post"
            action="#{facesContext.externalContext.requestContextPath}/j_security_check">
        <table>
            <tr>
                <td>User name:</td>
                <td><input type="text" name="j_username" /></td>
            </tr>
            <tr>
                <td>Password:</td>
                <td><input type="password"  name="j_password" /></td>
            </tr>
            <tr>
                <td><input type="submit"  value="Login" /></td>
            </tr>
        </table>
        </form>
    </ui:define>
</ui:composition>
</html>

/layout/layout.xhtml is accessible without authentification as this page is not placed inside my secured /pages/ folder. So the login.xhtml page looks perfect styled!

The real problem was how to jump into a secured page? I first have had a navigation.jsp page with a lot of jsf command links like:

<h:commandLink actionListener="#{workitemListBean.doRefresh}"
                    action="show_workitemlist">

My Navigation rule for "show_workitemlist" points to a secured page in the /pages folder.

faces-config.xml: 

......
    <navigation-case>
            <from-outcome>show_worklist</from-outcome>
            <to-view-id>/pages/workflow/worklist.jsp</to-view-id>
    </navigation-case>

But these commandLinks will not work because the JSF Framework will invoke all backing beans which are connected to the target page behind the navigation rule "show_workitmelist". And all my backing beans invoke a lot of EJBs which are secured using declarative JEE security.

So my command link did not show up the login.xhtml form as expected but throws a lot of "permission denied" exceptions :-(

The trick is to forward the anonymous user direct to the faces/ URL to access the secured page without JSF Navigation Rules. So I replaced my <h:commandLink> with a simple anchor tag:

<a href="#{facesContext.externalContext.requestContextPath}/faces/pages/workflow/worklist.jsp">
                <h:outputText value="#{global.login}" /></a>

So the result of these anchor tag is that the non authenticated user requests a secured page from my /faces/pages URL Pattern as defined in the web.xml.

The webContainer will invoke my Login Page, authenticate the user and after a successful login the JSF Framework starts up and builds all the necessary things to view the page with all backing-beans and EJBs. As the user is now authenticated everything works perfect as JSF has all the principal stuff and user informations to invoke my secured EJBs!

So: do not use commandLinks to login an anonymous user in a JSF Application inside a Facelets layouted login page.