Friday, September 10, 2010

Spring Dependency Injection with JBOSS : the CLASSPATH issue

When facing the problem of deploying web archives (war) to be configured through Spring dependency injection, you probably want to have generic applications that do not have to be recompile every time you deploy them on new configurations.

In my current project I need to configure a REST API with various parameters (host name, database paths, maximum of records per request). For this I use Spring dependency injection where the parameters are injected at run-time via a resource file located outside the war file, in a folder specified by the Windows CLASSPATH variable (my testing and production platforms are windows machine).

First I need to add a windows CLASSPATH system variable (in your system properties/environment variables)  if this variable does not exist. Then I add the resources.xml file directly in the folder specified by CLASSPATH. You can also use a sub-folder but you will need to hard-code the name of the folder in your spring config file - in my case applicationContext.xml located in ./src/main/webapp/WEB-INF/

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-2.5.xsd
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    <import resource="classpath:/resources.xml" />
</beans>

My resources.xml looks like this:

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
  <bean id="custService" 
                      scope="prototype"
                      class=".....">
   <property name="hostName" value="121.122.123.124"/>
   <property name="databasePath" value="..."/>
   <property name="maxRecordsPerRequest" value="1000"/>
  </bean>
</beans>

One issue you might encounter when you try to deploy your application on JBoss is that the web application server does not take into account the CLASSPATH out-of-the-box (I am using redhat EAP 5.0.X - production setting), but this might be also the case with JBOSS community edition.

Your war file will probably fail to deploy and you will find a bunch of errors in your log file ./jboss-as/server/<setting>/log/server.log  including:

org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: 
Failed to import bean definitions from URL location [classpath:/resources.xml]
Offending resource: ServletContext resource [/WEB-INF/applicationContext.xml]; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException:
IOException parsing XML document from class path resource [resources.xml]; 
nested exception is java.io.FileNotFoundException: 
class path resource [resources.xml] cannot be opened because it does not exist

What is missing is that you need to tell JBoss about your CLASSPATH variable.
Just edit ./jboss-as/bin/run.bat and add the CLASSPATH variable and you will be up and running in no time.

:RESTART
"%JAVA%" %JAVA_OPTS% ^
   -Djava.endorsed.dirs="%JBOSS_ENDORSED_DIRS%" ^
   -classpath "%JBOSS_CLASSPATH%;%CLASSPATH%" ^
   org.jboss.Main -b 0.0.0.0 -c production %*

Tuesday, August 24, 2010

RESTeasy JAX-RS embeddable server and SpringBeanProcessor

TJWS (Tiny Java Web Server and Servlet Container) is a very convenient miniature Java Web Server build as a servlet container with HTTPD servlet providing standard Web server functionality.

I have been using TJWS for testing a REST API to be deployed on JBoss application server. The advantage is that JUnit tests can run without the need to deploy a war file on JBoss. Since I have implemented the REST API with RESTEasy, I am using the embedded TJWS server part of the org.jboss.resteasy.plugins.server.tjws.TJWSEmbeddedJaxrsServer package.

The RESTEasy documentation (chapter 23) describes how to use the embedded container.

@Path("/")public class MyResource {

   @GET
   public String get() { return "hello world"; }
 
   public static void main(String[] args) throws Exception 
   {
      TJWSEmbeddedJaxrsServer tjws = new TJWSEmbeddedJaxrsServer();
      tjws.setPort(8081);
      tjws.getRegistry().addPerRequestResource(MyResource.class);
      tjws.start();
   }
}

As you can see, TJWS is very simple to use. You create an instance of the server, setup the port (this is very useful when for example certain ports are already used - I had to set a specific port for our Hudson continuous builds). Then you specify the class to test and you start the server.

In my JUnit tests, I start the server before each tests and stop it after the tests are completed:

private TJWSEmbeddedJaxrsServer server; 

@Before
    public void start() {
      
     server = new TJWSEmbeddedJaxrsServer();
     server.setPort(SERVER_PORT);
     server.getDeployment().getActualResourceClasses().add(MyResource.class);
     server.start();
    }

@After
    public void stop() {
     server.stop();
    }

Since I am using Spring I was interested to leverage the framework for dependency injection in order to configure certain server settings. However the RESTeasy documentation provides only some pseudo-code example:

public static void main(String[] args) throws Exception 
   {
      final TJWSEmbeddedJaxrsServer tjws = new TJWSEmbeddedJaxrsServer();
      tjws.setPort(8081);

      org.resteasy.plugins.server.servlet.SpringBeanProcessor processor = new SpringBeanProcessor(tjws.getRegistry(), tjws.getFactory();
      ConfigurableBeanFactory factory = new XmlBeanFactory(...);
      factory.addBeanPostProcessor(processor);

      tjws.start();
   }

I had to make some modifications to the code provided as follow:

@Before
    public void start() {
      
     server = new TJWSEmbeddedJaxrsServer();
     server.setPort(SERVER_PORT);
     server.getDeployment().getActualResourceClasses().add(MyResource.class);
     server.start();
     
     Resource resource = new FileSystemResource("src/test/resources/resources.xml");
     ConfigurableListableBeanFactory factory = new XmlBeanFactory(resource);
     SpringBeanProcessor processor = new SpringBeanProcessor(
             server.getDeployment().getDispatcher(),
             server.getDeployment().getRegistry(), 
             server.getDeployment().getProviderFactory());
     processor.postProcessBeanFactory(factory);
    }

Alternatively you can define your Spring resource file in a static string directly in your JUnit test class:

Resource resource = new ByteArrayResource(SPRING_BEAN_CONFIG_FILE.getBytes());

Wednesday, July 28, 2010

How to secure the JBoss JMX and Web Consoles?

Lately I have been using JBoss more and more as my deployment platform of choice. I am currently using the latest JBoss Enterprise Middleware solution (EAP version 5.0.1). This is a commercial version, but you can also use the community edition as well which offers most of the same features.

One of the issue I have encountered recently was how to secure the web based administration consoles?

As a matter of fact, the default installation offers a login and password for the admin console which is typically accessible on http://localhost:8080/admin-console if your web application runs locally, or more generally on http://<host>:<port>/admin-console.
However if you want to protect the JMX console (http://localhost:8080/jmx-console) and the JBoss Web console (http://localhost:8080/web-console) you have to make sure that certain files in your installation are setup correctly.


Generally, the JBoss community and RedHat are quite good at documenting the features of their products, but I was disappointed to find incomplete information in the main page on this subject.

This page explains that "the jmx-console and web-console are standard servlet 2.3 deployments that can
be secured using J2EE role based security.  Both also have a skeleton setup to allow one to easily enable security using username/password/role mappings found in the jmx-console.war and web-console.war deployments in the corresponding WEB-INF/classes users.properties and roles.properties files".

Until this point, it is quite clear. The difficulty starts with a vague description where to find the files in questions :

To secure the JMX Console using a username/password file -
  • Locate the  directory.  This will normally be in  directory..
The author probably assumes that the various locations are obvious to everyone. Let me be more precise and generous in details:


First you will need to know which profile/configuration you are running. JBoss EAP has six configurations based on your needs:
  • all (everything, including clustering support and other enterprise extensions)
  • default (for application developers)
  • minimal (the strict minimum)
  • production (everything but optimized for production environments)
  • standard (tested for Java EE compliance)
  • web (experimental lightweight configuration) 

    If you did not specify your profile explicitly at starting time (run.sh -c )you most likely use the default profile.





    You can check which profile is running by looking at your JBoss EAP Admin Console. The name of the profile/configuration is indicated at the top of the server hierarchy.

    By the way, the various applications that you will likely developed (war, ear, rar or jar files) will be deployed under the corresponding folders under the Applications node.

    First you might want to change the login and password of the admin console itself before adding those for the JMX and Web consoles?


    One important "meta" file is login-config.xml which is located under \jboss-as\server\ 

     





    This file specify for a specific profile (e.g. default) the security-domain values for the consoles:

    <application-policy name = "jmx-console">
        <authentication>
          <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
            flag="required">
            <module-option name="usersProperties">props/jmx-console-users.properties</module-option>
            <module-option name="rolesProperties">props/jmx-console-roles.properties</module-option>
          </login-module>
        </authentication>
      </application-policy> 

    <application-policy name = "web-console">
        <authentication>
          <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
            flag="required">
            <module-option name="usersProperties">web-console-users.properties</module-option>
            <module-option name="rolesProperties">web-console-roles.properties</module-option>
          </login-module>
        </authentication>
      </application-policy>

    In other words, this file can help you locate and map how authentication (login and password in users.properties file) and authorization (access control in roles.properties file) is specified.

    Since these consoles are themselves web applications, you will need to look at exploded war files under your profile, under the deploy folder.

    Securing the JMX Console:

    • Locate the folder jmx-console.war under ./server/<config>/deploy
    • Open the file ./server/<config>/deploy/mx-console.war/WEB-INF/web.xml
    • Verify that the <security-constraint> section is not commented (in this section, you should see specified  the roles for authorization (see below)
    <security-constraint>
         <web-resource-collection>
           <web-resource-name>HtmlAdaptor</web-resource-name>
           <description>An example security config that only allows users with the
             role JBossAdmin to access the HTML JMX console web application
           </description>
           <url-pattern>/*</url-pattern>
         </web-resource-collection>
         <auth-constraint>
           <role-name>JBossAdmin</role-name>
         </auth-constraint>
       </security-constraint>
    • Locate the file: .\server\<config>\conf\props\jmx-console-users.properties (if the file name has not been changed in login-config.xml
    • change admin=admin to your new <new_login>=<new_password>
    The authentication method is specified in the following section:
     <login-config>
          <auth-method>BASIC</auth-method>
          <realm-name>JBoss JMX Console</realm-name>
       </login-config>
    
       <security-role>
          <role-name>JBossAdmin</role-name>
       </security-role>

    Securing the Web Console:
    • Login credentials are the same as used for the JMX console - in : .\server\<config>\conf\props\jmx-console-users.properties 
    • change admin=admin to your new <new_login>=<new_password> 

    For more information and this topic you can also look at Securing the JMX Console and Web Console (HTTP).

    Thursday, June 10, 2010

    Response objects and the use of GenericEntity class with RESTEasy

    Recently during the implementation of a REST API, I wanted to return a complex response containing a list of objects (Patients). The issue was that the RESTEasy build-in JAXB MessageBodyWriter could not directly handle lists of JAXB objects (Java has trouble obtaining generic type information at runtime).

    I was recently in a situation where I had to create a complex response to a HTTP POST for my REST API. I am using JAXB /JSON support from RESTEasy.

    I found some element of answer in the book "RESTFul Java with JAX-RS" from Bill Burke (pp 102). However the code snippet had a couple of errors:

      • the GenericEntity object cannot be passed to the Response.ok() method directly (a ResponseBuilder is required).

      • references to GenericEntity needs to be parameterized.

    My use case is a little more complex than in the book. I am receiving a user-name and password from a POST (e.g. a form submit). I then perform the authentication and returns a list of Patient objects in a JSON/GZIP compressed format (instead a list of Customer objects) together with an authentication token.





    The resulting code looks like this:

    
       @POST
       @Path("/token")
       @Consumes("application/x-www-form-urlencoded")
       @Produces("application/json")
       @GZIP
       public Response getPatientsWithToken(@FormParam("username") String username, @FormParam("password") String password) {
      
            Login login = new Login(username, password);
            // ... perform authentication here ....
        
            // Build the returning patient list
            List<Patient> returnList = new ArrayList<Patient>();
            returnList.addAll(patients.values());
            Collections.sort(returnList);
          
            GenericEntity<List<Patient>> entity = new GenericEntity<List<Patient>>(returnList){};
          
            // Create the response
            ResponseBuilder builder = Response.ok(entity);
            return builder.build();
       }
    
    


    Of course you will have to import the following classes as well:


    import javax.ws.rs.core.GenericEntity;
    import javax.ws.rs.core.Response;
    import javax.ws.rs.core.Response.ResponseBuilder;
    

    Wednesday, June 9, 2010

    Open APIs: State of the Market, May 2010

    Today, I was looking at the presentation from John Musser related to Open APIs (see below). Even though these statistics comes mainly from mashup and consumer applications, I was surprised by the fact that REST APIs are gaining market shares over SOAP APIs so rapidly.

    In B2B and in the enterprise world in general SOAP is often the top choice. The advantages for SOAP often mentioned are:
    • Type checking (via the WSDL files)
    • Availability of development tools
    On the other hand, REST offers the following:
    • Lightweight and easy to build
    • Human Readable Results
    • Extensibility
    • Scalability

    In Health Care, SOAP is still widespread and prevalent. However there are some interesting projects such as NHIN Direct Health Information Exchange where the relevance of REST vs other API protocols are discussed.

    It will be interesting to see what will be the outcome of such discussions.

    Tuesday, June 1, 2010

    JAXB-JSON Rest API using RESTEasy on JBoss EAP

    In this second part of my evaluation of JBoss RESTEasy, I focus on adapting the JAXB-JSON samples provided by RESTEasy for JBoss Enterprise Application Platform 5.0.1.

    Earlier I find myself to adapt the maven POM file to have the proper dependencies for the Twitter RESTEasy client.

    Initially this simple JAXB-JSON sample had been designed to run on Jetty Web Server which run fine out-of-the box. However I had to make some modifications to the original project structure to have the code running as a simple eclipse project that can be deploy on JBoss EAP 5.0.X from RedHat (this will also work on Jboss community edition).

    The new project (eclipse) structure looks as below:





    Notice that I have also moved the code for both packages:  org.jboss.resteasy.annotations.providers.jaxb.json
    org.jboss.resteasy.plugins.providers.jaxb.json
    at the root of my project, since I am not using the remaining code of the example.

    I also made some additional adaptations for JBoss to some of the project files including:
    • pom.xml file
    • web.xml
    I also added a small test suite to test the REST API operations using JUnit which will work after the first deployment (I run JBoss locally on http://localhost:8080).

    By the way, make sure you have src/main/resources/META-INF/services/javax.ws.rs.ext.Providers included in your project.









    Here is the content of my new pom.xml file for JBoss:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>org.jboss.resteasy.examples</groupId>
        <artifactId>jaxb-json</artifactId>
        <version>0.1.0</version>
        <packaging>war</packaging>
        <name/>
        <description/>
    
        <repositories>
            <repository>
                <id>java.net</id>
                <url>http://download.java.net/maven/1</url>
                <layout>legacy</layout>
            </repository>
            <repository>
                <id>maven repo</id>
                <name>maven repo</name>
                <url>http://repo1.maven.org/maven2/</url>
            </repository>
            <!-- For resteasy -->
            <repository>
                <id>jboss</id>
                <name>jboss repo</name>
                <url>http://repository.jboss.org/maven2</url>
            </repository>
        </repositories>
        <dependencies>
        
            <!-- core library -->
            
            <dependency>
                <groupId>org.jboss.resteasy</groupId>
                <artifactId>resteasy-jaxrs</artifactId>
                <version>1.2.1.GA</version>
                <!-- filter out unwanted jars -->
                <exclusions>
                    <exclusion>
                        <groupId>commons-httpclient</groupId>
                        <artifactId>commons-httpclient</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>tjws</groupId>
                        <artifactId>webserver</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>javax.servlet</groupId>
                        <artifactId>servlet-api</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            
            <!-- optional modules -->
            
          <dependency>
                <groupId>org.jboss.resteasy</groupId>
                <artifactId>resteasy-jettison-provider</artifactId>
                <version>1.2.1.GA</version>
            </dependency>
            
            <!-- modules already provided by Java 6.0 -->
             
       <dependency>
           <groupId>javax.xml.bind</groupId>  
           <artifactId>jaxb-api</artifactId>
           <version>2.1</version>
           <scope>provided</scope>
       </dependency>
       
        <dependency>
             <groupId>junit</groupId>
              <artifactId>junit</artifactId>
              <version>4.1</version>
                     <scope>test</scope>
                 </dependency>
         
        </dependencies>
    
        <build>
            <finalName>jaxb-json</finalName>
            <plugins>
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>jboss-maven-plugin</artifactId>
                    <version>1.4</version>
                    <configuration>
                        <jbossHome>C:\JBoss\EnterprisePlatform-5.0.0.GA\jboss-as</jbossHome>
                 <contextPath>/</contextPath>
                 <serverName>default</serverName>
                 <fileName>target/jaxb-json.war</fileName>
              </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <configuration>
                        <source>1.5</source>
                        <target>1.5</target>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </project>
    
    

    I modified the web.xml for the URL looks more simple by removing the mapping to reasteasy:

    <?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>Archetype Created Web Application</display-name>
    
       <context-param>
          <param-name>javax.ws.rs.Application</param-name>
          <param-value>org.jboss.resteasy.examples.service.LibraryApplication</param-value>
       </context-param>
    
       <context-param>
          <param-name>resteasy.servlet.mapping.prefix</param-name>
          <param-value>/</param-value>
       </context-param>
    
       <listener>
          <listener-class>
             org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
          </listener-class>
       </listener>
    
       <servlet>
          <servlet-name>Resteasy</servlet-name>
          <servlet-class>
             org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
          </servlet-class>
       </servlet>
    
       <servlet-mapping>
          <servlet-name>Resteasy</servlet-name>
          <url-pattern>/</url-pattern>
       </servlet-mapping>
    
    </web-app>
    

    The JUnit code looks like this:

    package org.jboss.resteasy.examples.test;
     
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    import junit.framework.Assert;
    import junit.framework.Test;
    import junit.framework.TestCase;
    import junit.framework.TestSuite;
      
    public class LibraryTest extends TestCase
    {
        /**
         * Create the test case
         *
         * @param testName name of the test case
         */
        public LibraryTest( String testName )
        {
            super( testName );
        }
    
        /**
         * @return the suite of tests being tested
         */
        public static Test suite()
        {
            return new TestSuite( LibraryTest.class );
        }
    
          
        /**
         * Testing the Library REST API
         */
        
        public void testGetMapped()  
        {
         validateRESTCall("GET", "http://localhost:8080/jaxb-json/library/books/mapped");
         assertTrue( true );
        }
        
    
        public void testGetBadger()  
        {
         validateRESTCall("GET", "http://localhost:8080/jaxb-json/library/books/badger");
         assertTrue( true );
        }
        
        private void validateRESTCall(String method, String url) {
         
         try {
             System.out.println("*** "+method);
             URL resURL = new URL(url);
             System.out.println("URL: " + url.toString());
             HttpURLConnection connection = (HttpURLConnection) resURL.openConnection(); 
             connection.setRequestMethod(method);
             System.out.println("Content-Type: " + connection.getContentType());
             
             BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
     
             String line = reader.readLine();
             while (line != null)
             {
                System.out.println(line);
                line = reader.readLine();
             }
             Assert.assertEquals(HttpURLConnection.HTTP_OK, connection.getResponseCode());
             connection.disconnect();
         } catch (Exception err) { 
             System.out.print("Error in VHRResourceTest.validateRESTCall : " + err); 
            };
        }
    }
    

    To build I am using Maven (I recommend to install the maven eclipse plugin) with the goals mvn clean install compile package. Make sure also that before that you do a mvn eclipse:eclipse to update the dependencies in your project.

    To deploy jaxb-json.war file from eclipse (so I don't have to manually copy the war file from the target folder), I have installed the JBoss eclipse plugin. As a result I can make it deployable (accessible by a right-click) and it appear in the Eclipse JBoss server view:


    The REST API JSON Library resources are then accessible directly on a browser via http://localhost:8080/jaxb-json/library/books/mapped or http://localhost:8080/jaxb-json/library/books/badger.

    If you want to compress your response, RESTEasy provides GZIP Compression/Decompression support using a very simple @GZIP annotation:

       @GET
       @Path("books/mapped")
       @Produces("application/json")
       @GZIP
       public BookListing getBooksMapped()
       {
          return getListing();
       }

    Just import the following class:

    import org.jboss.resteasy.annotations.GZIP;

    Overall the adaptation from Jetty to JBoss was easy and the documentation very clear.

    Additional discussions, recommendations and information can be found on the JBoss Community.

    For an example of using REST architecture for Mobile Applications (HealthCare) see this post.

    Tuesday, May 18, 2010

    Enhanced POM for JBoss RESTEasy Twitter API Client Sample

    I recently looked at JBOSS RESTEasy as a way to create and test RESTful APIs. The platform looks very promising with a lot of praise from developers. Also the documentation seems very extensive and precise.

    I started by downloading RESTEasy 1.2.1 GA and tried the sample code. I started with a java client to access existing RESTful Web Services and APIs. Among the api-clients, there is a Twitter small client that works out-of-the box (located under /RESTEASY_1_2_1_GA/examples/api-clients/src/main/java/org/jboss/resteasy/examples/twitter).

    However when I started to extract the code and wanted to create a Maven 2 based stand-alone project, I encountered some issues related to JAR dependency conflicts, including the following error message also described here.

    java.lang.NoClassDefFoundError: Could not initialize class com.sun.xml.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl 
    

    The project (eclipse) structure looks as below:


















    I managed to fix these issues by modifying the POM file as follow:

    <?xml version="1.0" encoding="UTF-8"?>
        <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
     
        <groupId>org.jboss.resteasy.examples</groupId>
     <artifactId>api-clients</artifactId>
     <version>1.2.1.GA</version>
      
      <dependencies>
        <!-- Resteasy Core -->
        <dependency>
          <groupId>org.jboss.resteasy</groupId>
          <artifactId>resteasy-jaxrs</artifactId>
        </dependency>
        <!-- JAXB support -->
       <dependency>
          <groupId>org.jboss.resteasy</groupId>
          <artifactId>resteasy-jaxb-provider</artifactId>
       </dependency>
        
      </dependencies>
      <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.jboss.resteasy</groupId>
                    <artifactId>resteasy-bom</artifactId>
                    <version>1.2.1.GA</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
       </dependencyManagement>
       
       <!-- Build Settings --> 
       <build>
        <plugins>  
          <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
              <source>1.6</source>
              <target>1.6</target>
            </configuration>
          </plugin>
        </plugins>
       </build>
      
      <!-- Environment Settings -->
      <repositories>
        <repository>
          <id>jboss</id>
          <name>jboss repo</name>
          <url>http://repository.jboss.org/maven2</url>
         </repository>
       </repositories>
      
    </project>
    

    The most important piece, beside the cleaning of the POM file, was to include a pom that can be imported so the versions of the individual modules do not have to be specified (see RESTEasy documentation - Chapter 43. Maven and RESTEasy).

    I also made sure to have correct dependencies for resteasy-jaxrs and resteasy-jaxb-provider.

    As a result, I was able to compile the whole project without any errors (mvn clean compile) and run it to access the Twitter REST API

    mvn exec:java -Dexec.mainClass="org.jboss.resteasy.examples.twitter.TwitterClient" -Dexec.args="<userid> <password>"
    (Replace last parameters by your twitter user and password).

    The small client in question leverages JAX-RS annotations to read and write the Twitter API resources:

    package org.jboss.resteasy.examples.twitter;
    
    import java.util.Date;
    import java.util.List;
    
    import javax.ws.rs.FormParam;
    import javax.ws.rs.GET;
    import javax.ws.rs.POST;
    import javax.ws.rs.Path;
    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlRootElement;
    import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
    
    import org.apache.commons.httpclient.Credentials;
    import org.apache.commons.httpclient.HttpClient;
    import org.apache.commons.httpclient.UsernamePasswordCredentials;
    import org.apache.commons.httpclient.auth.AuthScope;
    import org.jboss.resteasy.client.ProxyFactory;
    import org.jboss.resteasy.client.ClientExecutor;
    import org.jboss.resteasy.client.core.executors.ApacheHttpClientExecutor;
    import org.jboss.resteasy.plugins.providers.RegisterBuiltin;
    import org.jboss.resteasy.spi.ResteasyProviderFactory;
    
    public class TwitterClient
    {
       static final String friendTimeline = "http://twitter.com/statuses/friends_timeline.xml";
    
       public static void main(String[] args) throws Exception
       {
          RegisterBuiltin.register(ResteasyProviderFactory.getInstance());
          final ClientExecutor clientExecutor = new ApacheHttpClientExecutor(createClient(args[0], args[1]));
          TwitterResource twitter = ProxyFactory.create(TwitterResource.class,
                "http://twitter.com", clientExecutor);
          System.out.println("===> first run");
          printStatuses(twitter.getFriendsTimelines());
          
          twitter
          .updateStatus("I programmatically tweeted with the RESTEasy Client at "
                + new Date());
          
          System.out.println("===> second run");
          printStatuses(twitter.getFriendsTimelines());
       }
    
       public static interface TwitterResource
       {
          @Path("/statuses/friends_timeline.xml")
          @GET
          Statuses getFriendsTimelines();
    
          @Path("/statuses/update.xml")
          @POST
          Status updateStatus(@FormParam("status") String status);
       }
    
       private static void printStatuses(Statuses statuses)
       {
          for (Status status : statuses.status)
             System.out.println(status);
       }
    
       private static HttpClient createClient(String userId, String password)
       {
          Credentials credentials = new UsernamePasswordCredentials(userId,
                password);
          HttpClient httpClient = new HttpClient();
          httpClient.getState().setCredentials(AuthScope.ANY, credentials);
          httpClient.getParams().setAuthenticationPreemptive(true);
          return httpClient;
       }
    
       @XmlRootElement
       public static class Statuses
       {
          public List<Status> status;
       }
    
       @XmlRootElement
       public static class Status
       {
          public String text;
          public User user;
    
          @XmlElement(name = "created_at")
          @XmlJavaTypeAdapter(value = DateAdapter.class)
          public Date created;
    
          public String toString()
          {
             return String.format("== %s: %s (%s)", user.name, text, created);
          }
       }
    
       public static class User
       {
          public String name;
       }
    
    }
    
    

    The small DateAdapter class is a utility class for date formatting:

    package org.jboss.resteasy.examples.twitter;
    
    import java.util.Date;
    import java.util.List;
    package org.jboss.resteasy.examples.twitter;
     
    import java.util.Date;
    import javax.xml.bind.annotation.adapters.XmlAdapter;
    import org.jboss.resteasy.util.DateUtil;
    
    public class DateAdapter extends XmlAdapter<String, Date> {
    
       @Override
       public String marshal(Date date) throws Exception {
           return DateUtil.formatDate(date, "EEE MMM dd HH:mm:ss Z yyyy");
       }
    
       @Override
       public Date unmarshal(String string) throws Exception {
           try {
               return DateUtil.parseDate(string);
           } catch (IllegalArgumentException e) {
               System.err.println(String.format(
                       "Could not parse date string '%s'", string));
               return null;
           }
       }
    }