Sunday 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.

 

Saturday May 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.

Sunday Dec 07, 2008

RichFaces - How to handle external Login mechanism like OpenID

Today I found a solution for a login problem I was faced with since a long time using RichFaces and Facelets in my JEE Web App.
The problem was that my Login Form uses an external login mechanism (OpenID) to log in the user.
After the first successful login the RichFaces page is not loaded correctly (styles and scripts are not loaded). If the user reloads the page after the first login everything works well.
I saw that some people are faced with this problem in similar situations. So I will try to explain my solution I found today.

My application has to areas - a unrestricted (/*) and a restricted (/secured/*) area. So when the user try to access a restricted (RichFaces) page (e.g. /secured/page-a.jsf) my loginForm - located in the unrestricted area (/login.jsf) appears. So the user can first perform a login. Typical for OpenID the login mechanims is handled by a Servlet. The Servlet knows the first Request to the restricted page. After successful login the Servlet will redirect the user again to that restricted page. But this (RichFaces)page now will not be rendered correctly because the request goes no longer through the RichFaces Servlet Filter. So CSS and Scrips will not be loaded!
I solved this situation as I changed the startup mechanism of my application. The first thing the user will see is the Loginpage itself! The LoginPage is located in an unrestricted area. Now after the user logged in successfull, the login form (servlet) will redirect the user to an restricted RichFaces Page. And in this case the restricted RichFaces Page will be rendered correctly as the full request goes now through the RichFaces Servlet Filter. This works as there is no cascading redirect through different servlets.

I know that this sounds a little bit confusing but it works for me. If you have found other solutions for that problem please let me know.

Saturday Aug 23, 2008

Turbo Eclipse

These days I started a new Eclipse Project: Turbo Eclipse

The idea behind turbo eclipse is to provide a small and easy to use eclipse distribution for maven developers based on Eclipse Ganymede. 

The goals of Turbo Eclipse are

  • minimum amount of Plugins
  • Full Maven support using Maven IDE Plugin
  • Full Subversion support using subclipse
  • Facelets Support using the Eclipse Facelets Project

The Project is hosted at dev.java.net:

https://turbo-eclipse.dev.java.net/

Feedback and Tips are welcome. If you would like to join the project contact me or request a project role on dev.java.net


Saturday Aug 16, 2008

Eclipse Ganymede - Maven2 - Facelets

I invested a lot of hours to find out how to configure Eclipse Ganymede in a way where it works well in a JEE Facelets Project. Currently development of Facelets Web apps is not supported by the Eclipse IDE and WebToolPlattform (WTP). I am not sure but maybe the Eclipse WTP Team did not like Facelets developers. It is not easy to get things like code completion for xhtml files to run out of the box.
So this is my story how I configure a Eclipse Workspace to work with a JEE facelets  web project.

I am using Eclipse Ganymede, Glassfish V2 and Maven2. These are the steps I go through:

1.) Install the Eclipse Facelets Plugin

The Eclipse Facelets Plugin is the key to develop xhtml files in eclipse. But it is brand new and - in the moment - not available trough  the eclipse update manager.
The Plugin allows you to work in xhtml files like in JSP files. You got code completion and also some nice template wizzards. This plugin is very useful if you want to develop a JEE Web Facelets Application.
If you are interessted in the project - this is the project homepage:
http://wiki.eclipse.org/JSF_Facelets_Tools_Project
And in this webinar you can see the cool features of the plugin:
http://live.eclipse.org/node/225

But in the moment it is very difficult to get the plugin. If you are not familiar with plugin development, checkout plugin source code from eclipse, compile and export plugins it become very hard.... :-(

So I download the sources and compiled the plugin code with the eclipse IDE. If you don't want to go this way 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!

2.) Setup Workplace for JSF Support

Now you need to do some configurations to support Eclipse with the necessary Server Environment and JSF Libraries. This is not a project specific configuration but a workspace specific! So if you start in a new Workspace you need to repeat these steps.

First add your Glassfish Server to the Server list. Switch to the Server View and add a Glassfish V2 Server. You need this server environment (target runtime) later in your web project.

Next stp is to add the JSF Implementation form Glassfish to your Web JSF Configuration. This is explained also by Cay Horstmann's Blog:
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.




Now Restart you Eclipse! (I beleve this is a important step).

3.) Setup your Web Project

Now this is the most critical part. And I am not sure if every step is really necessary but it seems to work for me.

So open your Web Project (or create a new one) and open the project properties. Go to "Project Facets".

Here you can now add the "JSF 1.2" and also the new "Facelets 1.0" support:

 

You will see a link "Further configuration required". Click on it and configure the dialog like this using the server configuration from Glassfish:




You will not see this configuration page again after you close the property dialog! So be carefull. The only way is to disable the Faclets and JSP Support - apply the settings - and re enable the settings again! (It seems to me that this is a plan from the WTP Developers to craze JEE Developers)

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

The Server Runtime Library of Glassfish (automatical created during adding the Glassish Server to the Server list before) 

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

 

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

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

 

Finaly your project library settings should look like this (Maven Dependencies is only visible if you work in Maven2 project as I do)


 Next check the Order of the Libs! This seems also to be very important:


Make sure that the Maven Entry is at the end of the list!

Now restart your Eclipse! If you are lucky you can now edit xhtml files with code completion support :-)




If it did not work...

But! When you work with Maven2 Projects and your xhtml files did not support code completion you need to check some things. I did not know while the project settings will not work after first configuration. I followed these additional steps:

1.) update you maven configuration of your web project
     ->maven->update project configuration
2.) check the order of the libraries
3.) check if you have added the a target runtime for glassfish and also the glassfish JSF-Impl. You can select the glassfish Server as your project target.
3.) Restart Eclipse and wait as long as all background jobs are finished before you test you xhtml editor.

So I hope this will helpe someones - every comments are wellcome!

Wednesday 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.