RSS Entries RSS
RSS Subscribe by Email

Maven on Eclipse Tutorial

Install Java and Maven

First off, make sure you have a Java JDK installed and that your JAVA_HOME environment variable points to it. You can check by typing “echo %JAVA_HOME%” in Windows or “echo $JAVA_HOME” in Linux. You’ll next want to download and install Maven by following the directions on their website.  Once Maven is installed, you’ll want to create a settings.xml file in your .m2 directory, which is located at ~/.m2 in Linux or C:\Documents and Settings\user\.m2 on Windows.  You can do this by copying the settings.xml file from the directory where Maven in installed to you .m2 directory.

Install m2eclipse

You’ll want to make sure your Eclipse installation is pointint at your JDK.  You can check by going to Window > Preferences > Java > Installed JREs.  You’ll also want to set the -vm flag in your eclipse.ini file which is located at the root of your Eclipse installation.  Here’s what my file looks like:

-showsplash
org.eclipse.platform
--launcher.XXMaxPermSize
256M
-framework
plugins\org.eclipse.osgi_3.4.0.v20080605-1900.jar
-vm
C:\Program Files\Java\jdk1.6.0_11\bin\javaw.exe
-vmargs
-Dosgi.requiredJavaVersion=1.5
-Xms40m
-Xmx512m

Finally, you get to install m2eclipse by opening up Eclipse and selecting Help > Software Updates… > Available Software > Add Site…  Then enter http://m2eclipse.sonatype.org/update/, check the newly added boxes, and press Install.

Create Your First Maven Project

Now for the fun.  You can create a Maven project in Eclipse by selecting New > Project… > Maven > Maven Project.  Check “Create a simple project” on the first screen and hit Next.  Enter the Group Id, Artifact Id, and Name.  For example, “com.benmccann.robot”, “window-robot”, “Window Robot”.  Now, at long last, you can do some actual programming.

Add Dependencies

It won’t be long before you’ll want to add dependancies.  Open the Maven Indexes View by selecting Window > Show View > Other… > Maven > Maven Indexes.  You’ll want to make sure you have the Maven Central Repository, so right-click the view and choose “Add Index”.  Enter http://repo1.maven.org/maven2/ for the Repository URL and hit Retrieve to fill in the Repository Id of central.  Now you can right-click the project and choose Maven > Add Dependancy.  We’ll add jUnit since you’ll probably want it anyway.  Type junit and you should see it populated into the box below.  Use the dropdown at the bottom to set a scope of “test” and hit OK.

Buy Me a Beer

Comments (1)

Struts 2 AJAX Tutorial – Dojo Autocompleter Example

Struts 2 comes with a Dojo Toolkit plugin which makes developing an AJAX application easier than ever.  In addition, the AJAX plugin I would most recommend is the Struts 2 JSON plugin.  In this example, we will use the two side-by-side to create an autocompleter.  In order to use the Ajax support provided in Struts 2, I would recommend Struts 2.1.2 or later.  Include struts2-dojo-plugin-2.1.2.jar and jsonplugin-0.30.jar in your WEB-INF/lib directory.

First, we will create the action for the field that we wish to autocomplete:

package com.lumidant.tutorial.struts2.action;

import java.util.HashMap;
import java.util.Map;

import com.opensymphony.xwork2.ActionSupport;
import com.lumidant.tutorial.struts.dao.*;

public class AutocompleteField extends ActionSupport {

    private String city;
    private Map<String,String> json;

    public String execute() throws Exception() {
        return SUCCESS;
    }

    public String getCities() throws Exception() {
        json = new HashMap<String,String>();

        if(city != null && city.length() > 0) {
            CityDao dao = new CityDao();
            List<City> cities = dao.getCitiesStartingWith(city);
            for(City city : cities) {
                map.put(city.getId(), city.getName() + ", " + city.getState().getAbbreviation());
            }
        }

        return SUCCESS;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public Map<String,String> getJson() {
        return json;
    }

}

The getCities method in our action acts on the input String city that we’re given and creates a Map of cities starting with that text.  The key of our Map is going to be the hidden option value while the value of our Map is going to be our option text.

Next, we will modify our struts.xml configuration file to utilize the JSON plugin by extending json-default:

<package name="example" extends="json-default">
  <action name="AutocompleteField" class="com.lumidant.tutorial.struts2.action.AutocompleteField">
    <result type="json><param name="root">json</param></result>
  </action>
</package>

The root parameter that we specify is the name of the variable from our Action that we want to have converted and serialized to a JSON output.

And finally, we get to create our .jsp view:

<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ taglib prefix="sx" uri="/struts-dojo-tags" %>

<html>
  <head>
    <sx:head />
  </head>
  <body>
    <s:url id="cityList" action="AutocompleteField" method="getCities" />
    <sx:autocompleter name="city" theme="ajax" href="{%cityList}" size="24" />
  </body>
</html>

For any of the Dojo plug-in features that you use, you will need to include the <sx:head /> tag, which includes the relevant JavaScript tags into your page’s head tag.  Then you can see that the autocompleter’s name attribute aligns with the city field in our Action and the url’s method attribute aligns with our Action’s getCities method.  Now, when you visit your new page and start typing in the text box, you should see the field autocompleting.  There are some other cool built-in Dojo tags that you should look at as well like the datetimepicker, which provides a really nice calendar.

Buy Me a Beer

Comments (8)

Struts 2 Tutorial – Struts Configuration

The struts.xml file defines the relationship between actions and .jsp views, the inclusion of interceptors, and possible result types.  It’s essential that you be able to handle at least basic configuration changes, so we’ll demonstrate the most important and frequently used below.

Packages: Extension, Namespaces, and More

For more complex applications, you will likely want to split the configuration between multiple packages.  In Struts 2.0.x, the the default package is struts-default.  Most of the time, extending this package is a pretty good place to start from.

<package name="example" extends="struts-default">
  <interceptors>
    <interceptor name="authorization" class="com.lumidant.tutorial.struts2.interceptor.AuthorizationInterceptor">

    <interceptor-stack name="authStack">
      <interceptor-ref name="authorization" />
      <interceptor-ref name="defaultStack" />
    </interceptor-stack>
  </interceptors>

  <global-results>
    <result name="error">/WEB-INF/pages/error.jsp</result>
  </global-results>

</package>

In the package above, we did not define any action mappings, but rather we defined some more general properties that we can share between other packages.   We can now extend the package we just defined when creating new packages.  This package and any that extend it will have all Action.ERROR results go to error.jsp.  We also defined a new interceptor and interceptor stack that our actions and packages can make use of.  In this example, you could imagine that we would have two other packages extending this one.  One package would contain pages that any user could visit.  The other package could contain pages requiring the user to be logged in, so we would set the default-interceptor-ref to “authStack” as shown below:

<package name="admin" namespace="/admin" extends="example">
  <default-interceptor-ref name="authStack"/>

  <action name="DeleteSomething_*" method="{1}" class="com.lumidant.tutorial.struts2.action.DeleteSomething">
    <result name="input">/WEB-INF/pages/deleteSomething.jsp</result>
    <result>/WEB-INF/pages/deleteSuccessful.jsp</result>
  </action>
</package>

We also introduced additional new topics in this example.  Firstly, you’ll see that we created a namespace.  That means that all the actions in this package will be accessed through a spearate URL.  In this example it is an “/admin” URL.  Also, you’ll see that we put the “*” wildcard in the action name.  What this is doing is taking what was located in the * and replacing the “{1}” with that string.  Since the “{1}” is located in the method attribute, we will be calling a method on our action.  So let’s say the user accesses /admin/DeleteSomething_input.action.  Then the input method of the DeleteSomething.java action will be called.  Assuming we did not define our own input method, then we will inherit the input method from ActionSupport, which will take us to the result named “input”, which in this example is the deleteSomething.jsp page.

Action Chaining

<action name="LogIn_*" method="{1}" class="com.lumidant.tutorial.struts2.action.LogIn">
  <result type="chain">ShowHomepage</result>
</action>

What happens when we don’t want to show a .jsp page as the result of our action, but instead want to continue on directly to another action?  We simply use the result type “chain” to forward to another action.

Redirect After Post

<action name="SubmitOrder_*" method="{1}" class="com.lumidant.tutorial.struts2.action.SubmitOrder">
  <result name="redirect" type="redirect-action">
    <param name="actionName">DisplayOrder</param>
    <param name="namespace">/user</param>
  </result>
</action>

Very often, after an action is taken, we want to redirect the user to a separate action.  For example, let’s say the user submits an order.  If we leave the URL in their browser as SubmitOrder.action and they hit refresh, then the order could be submitted a second time.  So after they submit an order, it’s probably better if we redirect them to another action, such as one displaying the order they just placed with a thank you message.

Buy Me a Beer

Comments

Struts 2 Tutorial – Interceptors

Interceptors are my favorite aspect of Struts 2. They inspect and/or act on a user’s request. There are three main uses cases that I’ll discuss here: intercepting before the action, between the action and view, and after the view. At the end, I’ll show you how to add your brand spankin’ new interceptor to your struts.xml file so that it is called on each request.

Intercepting Before the Action:

package org.lumidant.tutorial.struts2.interceptor;

import java.util.Map;

import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ValidationAware;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class AuthorizationInterceptor extends AbstractInterceptor {

	private static final String USER_KEY = "user";

	public String intercept(ActionInvocation invocation) throws Exception {
		Map session = invocation.getInvocationContext().getSession();
		if(session.get(USER_KEY) == null) {
			addActionError(invocation, "You must be authenticated to access this page");
			return Action.ERROR;
		}

		return invocation.invoke();
	}

	private void addActionError(ActionInvocation invocation, String message) {
		Object action = invocation.getAction();
		if(action instanceof ValidationAware) {
			((ValidationAware) action).addActionError(message);
		}
	}

}

You can see that we check to see if the user is authorized and present an error message if he/she is not logged in. We do this by adding an ActionError, which can be displayed on your view. If the user is logged in, then he/she proceeds normally.

Intercepting Between the Action and Generation of View:

package org.lumidant.tutorial.struts2.interceptor;

import java.util.Map;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.opensymphony.xwork2.interceptor.PreResultInterceptor;
import org.apache.struts2.ServletActionContext;

public class WirelessInterceptor extends AbstractInterceptor {

	private static final String RESULT_CODE_SUFFIX_WIRELESS = "Wireless";
	private static final String REQUEST_HEADER_ACCEPT = "Accept";
	private static final String ACCEPT_HEADER_WIRELESS = "vnd.wap";

	public String intercept(ActionInvocation invocation) throws Exception {

		invocation.addPreResultListener()(new PreResultListener() {
			public void beforeResult(ActionInvocation invocation, String resultCode) {

				// check if a wireless version of the page exists
				// by looking for a wireless action mapping in the struts.xml
				Map results = invocation.getProxy().getConfig().getResults();
				if(!results.containsKey(resultCode + RESULT_CODE_SUFFIX_WIRELESS)) {
					return;
				}

				// send to wireless version if wireless device is being used
				final String acceptHeader = ServletActionContext.getRequest().getHeader(REQUEST_HEADER_ACCEPT);
				if(acceptHeader != null && acceptHeader.toLowerCase().contains(ACCEPT_HEADER_WIRELESS)) {
					invocation.setResultCode(resultCode + RESULT_CODE_SUFFIX_WIRELESS);
				}
			}
		});

		return invocation.invoke();
	}
}

In this example, the action has already been taken, but we have not generated the view that the user will see yet. This allows us to send the user to a separate page if he/she is using a Blackberry. We check the Accept HTML header to see if the string “vnd.wap” is present and if so then we append “Wireless” to the result code. So if the action was going to send the user to the result “Success” then we will instead show them the result “SuccessWireless”. We could easily adopt this technique for a Google Android or an iPhone as well.

Intercepting after View Creation:

package org.lumidant.tutorial.struts2.interceptor;

import java.util.Map;

import org.hibernate.Transaction;
import org.marketcharts.data.dao.util.HibernateSessionFactory;

import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class HibernateInterceptor extends AbstractInterceptor {

	public String intercept(ActionInvocation invocation) throws Exception {
		try {
			return invocation.invoke();
		} catch(Exception e) {
			Transaction tx = HibernateSessionFactory.getSession().getTransaction();
			if(tx != null && tx.isActive()) {
				tx.rollback();
			}
			return Action.ERROR;
		} finally {
			HibernateSessionFactory.getSession().close();
		}
	}

}

This example uses Hibernate, an Object Relational Mapper (ORM), which is library for easy database access. Hibernate needs an open session when the view is created (Open Session in View Pattern) because it lazily accesses the database. If the session is closed and we go to access the database, then Hibernate will throw an Exception. So this interceptor provides a method to close the session after the view has already been created and all the database calls have been made.

Adding an Interceptor to your struts.xml:

<package name="example" extends="struts-default">
  <interceptors>
    <!--
      One possible use of an interceptor is to send the user to special version of the .jsp
  	view if they are using a Blackberry as shown above.
    -->
    <interceptor name="wireless" class="com.lumidant.tutorial.struts2.interceptor.WirelessInterceptor">

    <interceptor-stack name="wirelessStack">
      <interceptor-ref name="exception" />
      <interceptor-ref name="servlet-config" />
      <interceptor-ref name="i18n" />
      <interceptor-ref name="chain" />
      <interceptor-ref name="params" />
      <interceptor-ref name="wireless" />
    </interceptor-stack>
  </interceptors>

  <default-interceptor-ref name="wirelessStack" />
</package>

In this example, we’ve change the default interceptor stack to be a custom stack which we’ve created. You can also extend existing stacks.

Buy Me a Beer

Comments (4)

Struts 2 Tutorial – Creating Views

One of the first things you’ll want to do after getting started with Struts 2 is create more complex views.  For this example, let’s assume we have an action that returns a list of all the employees at our company:

package com.lumidant.tutorial.struts2.action;

import com.opensymphony.xwork2.ActionSupport;
import com.lumidant.tutorial.struts.dao.*;
import com.lumidant.tutorial.struts.model.*;

public class ExampleAction extends ActionSupport {

    private static final long SerialVersionUID = 1L;
    private List<Employee> employees;

    public String execute() throw Exception {
        EmployeeDao dao = new EmployeeDao();
        employees = dao.getAllEmployees();
        return SUCCESS;
    }

    public List<Employee> getEmployees() {
        return employees;
    }

}

Now let’s create a page that iterates through our list of employees and prints each employee’s name in alternating row colors:

<%@ taglib prefix="s" uri="/struts-tags" %>

<html>
  <head>
    <title>Struts 2 Tutorial Example</title>
    <style type="text/css">
      .odd td { background-color: #fff; }
      .even td { background-color: #eee; }
    </style>
  </head>
  <body>
    <h2>All Employees:</h2>
    <table>
      <s:iterator value="employees" status="rowstatus">
        <tr <s:if test="#rowstatus.odd">class="odd"</s:if><s:else>class="even"</s:else>>
          <td class="fn n">
            <span class="given-name"><s:property value="firstName" /></span>
            <span class="additional-name"><s:property value="middleName" /></span>
            <span class="family-name"><s:property value="lastName" /></span>
          </td>
        </tr>
      </s:iterator>
    </table>
  </body>
</html>

What we just demonstrated is a fairly common use case and should provide a good example for doing the same in the future.  Also notice our use of the if tag, which you will undoubtedly find a need for.  Another common use case is to access the session from within the view.  For example, you may want to show a link only to logged in users.  Again, we will use OGNL to accomplish this.

<s:if test="%{#session.user.isAdmin()}">
  <a href="Admin.action">Only Admins Should See This Link</a>
</s:if>

That should give you a pretty good idea of the basics, so we’ll move onto an internationalization example.  You’ll want to create a package.properties file in the directory where your actions reside:

form.label.firstName=First Name:
form.label.lastName=Last Name:

This file contains text for the default translation of your site.  All static text on your site should be contained in an internationalization file.  You can then include the text in your JSP with the Struts 2 text tag in the following manner: <s:text name=”form.label.firstName” />.  You can create a package.properties file for each translation and append the suffix for each translation language (and optionally country – eg. en_US). For example, below is a package_pt.properties file, which contains a Portuguese translation of our example site:

form.label.firstName=Primeiro Nome:
form.label.lastName=Último Nome:

Now when the user visits the site, Struts will detect their browser language and serve the appropriate page to them.

That should give you pretty decent idea of how to create views for your site.  Please check out our other Struts 2 tutorials for information on other aspects of Struts 2.

Buy Me a Beer

Comments (3)

Struts 2 Tutorial – Getting Started

Struts 2 is an MVC web development framework.  It is based off of Web Work and has far less configuration than the original Struts.  I would strongly recommend Struts 2 over Struts for new development due to the faster development times it allows.  This is a very simple example and follow up posts will be coming shortly to help you develop more complex apps with Struts 2.

Getting Started

Below is an example project layout that you can use for your project.  It may be useful in helping you to decide where in your project to place your various files.

Struts 2 Project Layout

To get started, you’ll need to download the Struts libraries.  At a minimum, you will need to put the following in your WEB-INF/lib directory:

  • struts2-core.jar (The framework itself)
  • xwork.jar (Struts 2 is built on the XWork 2 framework)
  • ognl.jar (Object Graph Notation Language is used throughout the framework to access object properties)
  • freemarker.jar (Freemarker is used to create UI tag templates in Struts 2)
  • commons-logging.jar (Used to log to log4j or JDK logging)

Now we need to add a filter mapping to your web.xml file in order to have the Struts called whenever a page on your site is accessed:

<?xml version="1.0"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
  <filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
  </filter>

  <filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

It’s now time to make your first action.

package com.lumidant.tutorial.struts2.action;

import com.opensymphony.xwork2.ActionSupport;
import com.lumidant.tutorial.struts2.dao.*;
import com.lumidant.tutorial.struts2.model.*;

public class ExampleAction extends ActionSupport {

    private static final long SerialVersionUID = 1L;
    private String id;
    private Employee employee;

    public String execute() throw Exception {
        EmployeeDao dao = new EmployeeDao();
        employee = dao.getEmployeeById(id);
        return SUCCESS;
    }

    public Employee getEmployee() {
        return employee;
    }

    public void setId(String id) {
        this.id = id;
    }

}

There are a couple important things to note here.  The first is that our Action extends ActionSupport, which is a pattern you’ll want to continue for future actions.  Secondly, the input to our page has a setter which the framework needs to have present and the output has a getter.  Finally, our Action returns the result type SUCCESS.  The other predefined result types are ERROR, INPUT, LOGIN, and NONE.

Struts places its configuration in a struts.xml file. A good place to put it is at the root of your source folder. We’ll need to add our new action to the struts.xml file.

<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
  <!-- Configuration for the default package. -->
  <package name="default" extends="struts-default">
    <action name="ExampleAction" class="com.lumidant.tutorial.struts.action.ExampleAction">
      <result name="success">/WEB-INF/pages/displayEmployee.jsp</result>
    </action>
  </package>
</struts>

And finally, we need to create a .jsp view for our results to be rendered in.

<%@ taglib prefix="s" uri="/struts-tags" %>

<html>
  <head>
    <title>Struts 2 Tutorial Example</title>
  </head>
  <body>
    <h2>Selected Employee:</h2>
    <span class="fn n">
      <span class="given-name"><s:property value="employee.firstName" /></span>
      <span class="additional-name"><s:property value="employee.middleName" /></span>
      <span class="family-name"><s:property value="employee.lastName" /></span>
    </span>
  </body>
</html>

The important takeaway for the view is the manner in which properties can be accessed from the view.  Struts 2 uses OGNL, which for the majority of cases means you’ll just leave the get off of your method name.  For example <s:property value=”employee.firstName” /> will call your Action’s getEmployee() method and then will call the Employee’s getFirstName() method.

So now you should have an end-to-end working example.  Depending on which application server you’re using, you should be able to access your sample page at a url like http://localhost:9090/ExampleAction.action  You’ll of course need to create some sort of dummy EmployeeDao if you’re going to use this exact example, but you should be well on your way.

You’ll also want to continue reading about Struts 2 in the continuation of this tutorial:
Struts 2 Tutorial – Creating Views
Struts 2 Tutorial – Interceptors
Struts 2 Tutorial – Struts Configuration
Struts 2 AJAX Tutorial – Dojo Autocompleter Example

As an optional, but nice complement, I’d also recommend SiteMesh Tutorial with Examples.

Buy Me a Beer

Comments (2)

SiteMesh Tutorial with Examples

SiteMesh is a web layout framework for Java.  It differs from from frameworks such as Tiles in that it utilizes the decorator pattern.  For example, you create a number of pages and then you tell SiteMesh that you’d like to add the same header, footer, and menus to each of those pages.  This tutorial will give you a simple example of how SiteMesh can be used to give you a cleaner layout architecture and speed development times.

Start by downloading SiteMesh and adding sitemesh-2.3.jar to your WEB-INF/lib directory.  Then add the SiteMesh filter to your web.xml file like so:

<filter>
    <filter-name>sitemesh<filter-name>
    <filter-class>
        com.opensymphony.module.sitemesh.filter.PageFilter
    </filter-class>
<filter>

<filter-mapping>
    <filter-name>sitemesh<filter-name>
    <url-pattern>/*</url-pattern>
<filter-mapping>

This will call the SiteMesh filter whenever a page on your site is accessed.  Now we’ll need to create a /WEB-INF/decorators.xml file:

<decorators defaultdir="/WEB-INF/decorators">
    <decorator name="main" page="main.jsp">
        <pattern>/WEB-INF/pages/*</pattern>
    </decorator>
<decorators>

This will decorate all of the pages located under /WEB-INF/pages/ with the decorator /WEB-INF/decorators/main.jsp, which we’ll create next:

<%@ taglib prefix="decorator" uri="http://www.opensymphony.com/sitemesh/decorator" %>

<head>
  <title>
    Lumidant.com - <decorator:title default="SiteMesh Tutorial Example" />
  </title>
  <style type="text/css">@import "css/global.css";</style>
  <decorator:head />
  <body>
    <div id="header">
      <h2><a href="http://www.lumidant.com/">Lumidant.com</a> Tutorials</h2>
    </div>
    <div id="content">
      <decorator:body />
    </div>
  </body>
</html>

This decorator does a couple of things.  First off, it create an HTML title tag, which starts as “Lumidant.com – ” and then appends the title of the page that is being decorated.  If that page does not have a title tag, then a default is used to render “Lumidant.com – SiteMesh Tutorial Example”.  It then adds a global style sheet to every page being decorated and appends whatever is in that page’s head tag, which is useful for page-specific JavaScript, etc.  The decorator continues by adding a header to each page reading “Lumidant.com Tutorials” followed by the decorated page’s content.

Pretty cool, right?  If anyone is familiar with a similar decorator framework in PHP, please let me know.

Buy Me a Beer

Comments (7)

Apache CXF Tutorial – WS-Security with Spring

This tutorial will cover adding an authentication component to your web service though WS-Security. If you need an overview of how to setup CXF then you may find our previous tutorial helpful. Another helpful resource is CXF’s own WS-Security tutorial. However, it does not include information on how to setup the client through Spring.

To begin with, make sure you have at least the following .jars in addition to the required base CXF .jars:

spring-beans-2.0.6.jar
spring-context-2.0.6.jar
spring-core-2.0.6.jar
spring-web-2.0.6.jar
wss4j-1.5.1.jar
xmlsec-1.3.0.jar

Now we will add a security interceptor to the server’s Spring configuration file, which we named cxf.xml in the last tutorial in order to match the CXF documentation.

<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:jaxws="http://cxf.apache.org/jaxws"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
                          http://www.springframework.org/schema/beans/spring-beans.xsd
                          http://cxf.apache.org/jaxws
                          http://cxf.apache.org/schemas/jaxws.xsd">

  <import resource="classpath:META-INF/cxf/cxf.xml" />
  <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
  <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

  <jaxws:endpoint id="auth"
                  implementor="com.company.auth.service.AuthServiceImpl"
                  address="/corporateAuth">

    <jaxws:inInterceptors>
      <bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor" />
      <bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
        <constructor-arg>
          <map>
            <entry key="action" value="UsernameToken" />
            <entry key="passwordType" value="PasswordText" />
            <entry key="passwordCallbackClass" value="com.company.auth.service.ServerPasswordCallback" />
          </map>
        </constructor-arg>
      </bean>
    </jaxws:inInterceptors>

  </jaxws:endpoint>

</beans>

You can change the action and passwordType to do more advanced authentication. In this example, we will simply require all authenticating clients to know a single password specified by the server. If you’d like each client to have it’s own password you can specify that in the callback, which is the next thing we must implement:

package com.company.auth.service;

import java.io.IOException;
import java.util.ResourceBundle;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.ws.security.WSPasswordCallback;

public class ServerPasswordCallback implements CallbackHandler {

    private static final String BUNDLE_LOCATION = "com.company.auth.authServer";
    private static final String PASSWORD_PROPERTY_NAME = "auth.manager.password";

    private static String password;
    static {
        final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_LOCATION);
        password = bundle.getString(PASSWORD_PROPERTY_NAME);
    }

    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {

        WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];

        // Set the password on the callback. This will be compared to the
        //     password which was sent from the client.
        // We can call pc.getIdentifer() right here to check the username
        //     if we want each client to have it's own password.
        pc.setPassword(password);
    }

}

The server is now setup to require a password. The password we are requiring is one that we specified in a properties file and then read in through a ResourceBundle. You may find it easier to simply hard code the password on the initial run and then replace it with your own means of authentication once the service is up and running.

If you are running on WebLogic 9, as I was, then you will get an error “java.lang.UnsupportedOperationException: This class does not support SAAJ 1.1“. In order to correct that, make sure your version of the SAAJ classes are being used by adding the following to your weblogic.xml descriptor file:

<container-descriptor>
    <prefer-web-inf-classes>true</prefer-web-inf-classes>
</container-descriptor>

You WebLogic folks must also then set two properties in your WebLogic JDK:

-Djavax.xml.soap.MessageFactory=com.sun.xml.messaging.saaj.soap.ver1_1.SOAPMessageFactory1_1Impl
-Djavax.xml.soap.SOAPConnectionFactory=weblogic.wsee.saaj.SOAPConnectionFactoryImpl

We now have to setup the client to supply a password. Firstly, we will create another Spring file at com/company/auth/service/cxfClient.xml to setup the application context for the client:

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:jaxws="http://cxf.apache.org/jaxws"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
                      http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

  <bean id="proxyFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
    <property name="serviceClass" value="com.company.auth.service.AuthService"/>
    <property name="address" value="http://localhost:7001/authManager/services/corporateAuth"/>
    <property name="inInterceptors">
      <list>
        <ref bean="logIn" />
      </list>
    </property>
    <property name="outInterceptors">
      <list>
        <ref bean="logOut" />
        <ref bean="saajOut" />
        <ref bean="wss4jOut" />
      </list>
    </property>
  </bean>

  <bean id="client" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean" factory-bean="proxyFactory" factory-method="create" />

  <bean id="logIn" class="org.apache.cxf.interceptor.LoggingInInterceptor" />
  <bean id="logOut" class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
  <bean id="saajOut" class="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor" />
  <bean id="wss4jOut" class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
    <constructor-arg>
      <map>
        <entry key="action" value="UsernameToken" />
        <entry key="user" value="ws-client" />
        <entry key="passwordType" value="PasswordText" />
        <entry key="passwordCallbackClass" value="com.company.auth.service.ClientPasswordCallback" />
      </map>
    </constructor-arg>
  </bean>    

</beans>

We then need to set the password for our message:

package com.company.auth.service;

import java.io.IOException;
import java.util.ResourceBundle;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.ws.security.WSPasswordCallback;

public class ClientPasswordCallback implements CallbackHandler {

    private static final String BUNDLE_LOCATION = "com.company.auth.authClient";
    private static final String PASSWORD_PROPERTY_NAME = "auth.manager.password";	

    private static String password;
    static {
        final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_LOCATION);
        password = bundle.getString(PASSWORD_PROPERTY_NAME);
    }	

    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {

        WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];

        // set the password for our message.
        pc.setPassword(password);
    }

}

Finally, we create the service factory, which is extremely easy since all the work was done in the Spring file:

package com.company.auth.service;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public final class AuthServiceFactory {

    private static final ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {
                "com/company/auth/service/cxfClient.xml"
            });

    public AuthServiceFactory() {
    }

    public AuthService getService() {
        return (AuthService) context.getBean("client");
    }
}

Congratulations. Your web service now utilizes a basic implementation of WS-Security. Hopefully, that will be enough background to get you on your way.

Buy Me a Beer

Comments (30)

Gradient Web 2.0 Effects with GIMP

In my last post, I mentioned that I installed GIMP to read a Photoshop .psd file. If you’re not familiar with GIMP, it is an extremely high quality free alternative to Photoshop. Using GIMP, I have been able to create several graphical effects with little effort. In this post, I will show you how I created the logos for Lumidant and Moon Rock Media using GIMP.

Moon Rock came to us and wanted a “cliché web 2.0 design”. Basically that means they were asking for gradients, mirrored surfaces, reflections, and shiny or glossy images. To begin the logo, I created a gradient background. Select one color of gray as the foreground and another as the background. Then choose the gradient tool and drag it vertically from the top of the image to the bottom. Play around with this for a little to get a feel for the tool. Once that was completed, I used the text tool to write moon in blue and then rock in pink. I then chose the dodge/burn tool to alternately dodge and burn the pink letters:

Moonrock Logo - Text Only

Once I was certain the text was how I wanted, I stacked the two text layers to become a single layer, making them easier to work with. To mirror the text, you simply Duplicate Layer and then Flip Vertically. Position it below the original text. Now, under the transparency menu, Add Alpha Channel to the layer. This will allow us to make use of transparency. If the option was grayed out, then your layer already has an alpha channel, so you can just continue to the next step. The final step is to create another gradient effect. We want to use the gradient to hide the portion of the reflection we don’t want to see. I changed the foreground to black. Most importantly, you must click the picture of the gradient you’re creating in the gradient tool options and select “FG to Transparent”. Now drag the gradient tool up vertically over the text. This will hide most of the text with a black gradient:

Moonrock Logo with Black Gradient Hiding Reflection

Since we don’t want the black to show in the final logo, select Color to Alpha and choose black. Now the black will have disappeared leaving you with a finished reflection effect:

Moon Rock Media Logo

In the Lumidant logo on the Lumidant homepage, the lighthouse searchlight or spotlight was also created using gradient effects. To create a spotlight, first create a new layer. This is important because we will duplicate the layer later and only want the spotlight itself duplicated. Draw the outline of the light you’d like to create by using the paths tool. I created the light by drawing a long triangle. After you have drawn the third point and would like to connect back to the first, hold Ctrl and click on the first point. This will close the shape. Then hold Ctrl, click on the short side of the triangle, and drag it outwards. This will round the end of the light. Turn the shape into a selection by clicking “Selection from Path”:

Lumidant Logo with Searchlight Path Drawn

Now, we get to use the gradient tool again. Having created the spotlight-shaped selection, we can draw inside the selection and nothing outside of it will be affected. Select white and “FG to Transparent”. Drag the gradient tool from the point of the triangle to the end of the rounded section. Now Duplicate Layer. Add a 4px Gaussian Blur filter to one of the layers. In the “Layers, Channels, Paths, Undo” menu bar (referred to as a dialog by GIMP), select the layer that you blurred and move the opacity down to 80. Now choose the original spotlight layer and move the opacity down to 20. Hooray! You’ve just created an awesome looking spotlight.

Buy Me a Beer

Comments (16)

Web Services Tutorial with Apache CXF

I created a web service today with CXF and wanted to share the steps it took to get it up and running in this quick tutorial. Apache CXF was created by the merger of the Celtix and XFire projects. I chose to implement my service in CXF because some colleagues had been using XFire and would likely want to upgrade at some point. I am using the latest version, which is 2.0.4. While the library itself seems to be of high quality, the documentation is still a work in progress. However, do not fret because this CXF tutorial will get you up and running in no time. I will be creating a simple web service that will allow the retrieval of employee information. The service will return this simple POJO (Plain Old Java Object) bean with matching getters and setters:

package com.company.auth.bean;

import java.io.Serializable;
import java.util.Set;

public class Employee implements Serializable {

	private static final long serialVersionUID = 1L;
	private String gid;
	private String lastName;
	private String firstName;
	private Set<String> privileges;

	public Employee() {}

	public Set<String> getPrivileges() {
		return privileges;
	}

	public void setPrivileges(Set<String> privileges) {
		this.privileges = privileges;
	}	

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getGid() {
		return gid;
	}

	public void setGid(String gid) {
		this.gid = gid;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public boolean isUserInRole(String role) {
		if(privileges == null) { return false; }
		else { return privileges.contains(role); }
	}

}

First off, you need to download Apache CXF and drop the necessary .jars in your WEB-INF/lib directory:

aopalliance-1.0.jar
commons-logging-1.1.jar
cxf-2.0-incubator.jar
geronimo-activation_1.1_spec-1.0-M1.jar (or Sun’s Activation jar)
geronimo-annotation_1.0_spec-1.1.jar (JSR 250)
geronimo-javamail_1.4_spec-1.0-M1.jar (or Sun’s JavaMail jar)
geronimo-servlet_2.5_spec-1.1-M1.jar (or Sun’s Servlet jar)
geronimo-ws-metadata_2.0_spec-1.1.1.jar (JSR 181)
jaxb-api-2.0.jar
jaxb-impl-2.0.5.jar
jaxws-api-2.0.jar
jetty-6.1.5.jar
jetty-util-6.1.5.jar
neethi-2.0.jar
saaj-api-1.3.jar
saaj-impl-1.3.jar
spring-core-2.0.4.jar
spring-beans-2.0.4.jar
spring-context-2.0.4.jar
spring-web-2.0.4.jar
stax-api-1.0.1.jar
wsdl4j-1.6.1.jar
wstx-asl-3.2.1.jar
XmlSchema-1.2.jar
xml-resolver-1.2.jar

The first thing which needed to be done was to create the service interface. The service interface defines which methods the web service client will be able to call. It’s pretty standard Java with just two JWS (Java Web Service) annotations thrown in:

package com.company.auth.service;

import javax.jws.WebService;
import javax.jws.WebParam;
import com.company.auth.bean.Employee;

@WebService
public interface AuthService {
    Employee getEmployee(@WebParam(name="gid") String gid);
}

The @WebParam annotation is in fact optional, but highly recommended since it will make like easier for the end consumers of your service. Without it, your parameter would be named arg0 making it less clear what parameters your service actually takes.

Implementing the actual service comes next:

package com.company.auth.service;

import javax.jws.WebService;

import com.company.auth.bean.Employee;
import com.company.auth.dao.EmployeeDAO;

@WebService(endpointInterface = "com.company.auth.service.AuthService", serviceName = "corporateAuthService")
public class AuthServiceImpl implements AuthService {

	public Employee getEmployee(String gid) {
		EmployeeDAO dao = new EmployeeDAO();
		return dao.getEmployee(gid);
	}

}

I then had to tell Spring (which is used by CXF) where to find my Java classes. I created the following cxf.xml file inside my package directory (com/company/auth/service):

<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:jaxws="http://cxf.apache.org/jaxws"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
 					http://www.springframework.org/schema/beans/spring-beans.xsd
 					http://cxf.apache.org/jaxws
 					http://cxf.apache.org/schemas/jaxws.xsd">

  <import resource="classpath:META-INF/cxf/cxf.xml" />
  <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
  <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
  <jaxws:endpoint id="auth"
                  implementor="com.company.auth.service.AuthServiceImpl"
                  address="/swAuth"/>
</beans>

Finally, I updated my WEB-INF/web.xml file to let CXF know where my cxf.xml file was and define the CXF servlet:

<?xml version="1.0"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
  <display-name>Auth Manager</display-name>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:com/company/auth/service/cxf.xml</param-value>
  </context-param>
  <listener>
    <listener-class>
      org.springframework.web.context.ContextLoaderListener
    </listener-class>
  </listener>
  <servlet>
    <servlet-name>CXFServlet</servlet-name>
    <servlet-class>
        org.apache.cxf.transport.servlet.CXFServlet
    </servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>CXFServlet</servlet-name>
    <url-pattern>/services/*</url-pattern>
  </servlet-mapping>
</web-app>

The most frustrating portion of getting the CXF web service up and running was the following exception:
Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: javax.jws.WebService.portName()Ljava/lang/String;

This is due to the fact that I am running WebLogic 9.2, which contains a library with an older version of JSR (Java Specification Request) 181. The quickest solution for me was to prepend geronimo-ws-metadata_2.0_spec-1.1.1.jar to the WebLogic classpath. This will likely not be the solution I choose to implement in the end, but it got me back up and running. It seemed I also had to clear my WebLogic cache for this fix to take effect. Because I often find instances where this seems necessary, I have created a Windows script to clear the Weblogic Cache. If you run into app server related issues, this was one area I found the Apache CXF docs to be helpful.

Also, if you are running Hibernate, you may encounter ASM incompatibilities between Hibernate’s CGLib and the version of ASM which CXF requires. But do not fret because this is easy enough to solve.

Once this was solved, the list of services was available. The context root for my web project is authManager, so my regular web index page is available at http://localhost:7001/authManager/. The list of web services is then automagically generated by CXF at http://localhost:7001/authManager/services/.

The final step is to build the client. This was very easy when compared to getting the server up and running because I was able to simply swipe the code from the Apache CXF documentation. So, without further ado:

package com.company.auth.client;

import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

import com.company.auth.bean.Employee;
import com.company.auth.service.AuthService;

public final class Client {

    private Client() {
    } 

    public static void main(String args[]) throws Exception {

    	JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();

    	factory.getInInterceptors().add(new LoggingInInterceptor());
    	factory.getOutInterceptors().add(new LoggingOutInterceptor());
    	factory.setServiceClass(AuthService.class);
    	factory.setAddress("http://localhost:7001/authManager/services/swAuth");
    	AuthService client = (AuthService) factory.create();

    	Employee employee = client.getEmployee("0223938");
    	System.out.println("Server said: " + employee.getLastName() + ", " + employee.getFirstName());
    	System.exit(0);

    }

}

Wow! Wasn’t that cool? (Yes, I’m a dork :o ) You should now be up and running with a CXF web service.

If you are looking for something to learn next then may I suggest our tutorial on adding security to your web service.  That tutorial will also show you how to setup the client using Spring, which you may find helpful as well.

Buy Me a Beer

Comments (60)