Disable response schema validation CXF on JBoss 7.1

JBoss 7.1 ships with a new framework for Web services from Apache, called CXF.
This framework, when consuming SOAP web services, validates by default all responses against the provided wsdl.

Sometimes that behavior is not required because of several reasons. For example, the WSDL may change from time to time, adding attributes to the response, which won’t affect the current behavior of the application, or maybe from a performance perspective, since this validation requires an additional step in each request.

Making a long story short, to disable the schema validation for all SOAP responses, the standalone.xml should be edited, adding the following tag inside

<client-config name="Standard-Client-Config">
  <property name="set-jaxb-validation-event-handler" value="false"/>
</client-config>

This configuration disables the validation for all web service clients deployed in the server.

If this is too much for you, you can disable validation programatically only for the clients you need, adding the following line before calling the web service:

((BindingProvider) wsClient).getRequestContext().put("set-jaxb-validation-event-handler", "false");
Advertisements

Maven y conflictos entre dependencias

Compañeros, compañeras:

Comparto mi experiencia con maven para que nadie vuelva a sufrir lo que he sufrido yo..

Resulta que el maven me estaba generando un paquete y al ejecutarlo, me daba error porque no encontraba una clase. Mirando el ear generado, efectivamente veía en la carpeta lib, el jar con la clase que no estaba pudiendo encontrar.
Hete aquí, que no entendía por qué no la veía!
Mirando un poco más, vi que me estaba agregando también una librería con nombre distinto, pero se correspondía a una versión anterior, a nombrar, me estaba trayendo las librerías bcprov-jdk14 y bcprov-jdk15.
Primero, se ve que jboss cargaba la 14 y no le daba bolilla a la 15. Después que me di cuenta de eso, supe que tenía que eliminar la 14.
Ahora, cómo hago para saber quién estaba trayendo esa versión!? Yo estaba agregando a mano la 15 como dependencia, pero la otra.. ni idea.
Para eso, maven tiene un target mágico… ejecutando:
 

mvn dependency:tree
Te dice clarito qué dependencias tenés y el árbol de dependencias de cada uno de esos.
Pude identificar el que me estaba trayendo (era jasperreports). Luego de eso, solo falta agregar la regla de exclusión para que no traiga las librerías que dan conflicto, y listo!
La dependencia de jasperreports quedó así:

<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>5.1.0</version>
<exclusions>
    <exclusion>
      <groupId>bouncycastle</groupId>
      <artifactId>bcprov-jdk14</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.bouncycastle</groupId>
      <artifactId>bcprov-jdk14</artifactId>
    </exclusion>
  </exclusions>
</dependency>
 
Saluditos!

How to use Log4J in ejb module in Jboss7.1

JBoss 7.1 already ships with Log4J, but the config is somehow different from previous versions of the server.
The same Log4J architecture applies, you have appenders and categories, but the config files are different, so I’ll explain how to configure a new category and appender for this.

When developing your EJB you need to:

  1. import the Logger class: import org.apache.log4j.Logger;
  2. If the import does not resolve, add this jar to the path: %JBOSS_HOME%\modules\org\apache\log4j\main\log4j-1.2.16.jar
  3. create a field with the logger: private static Logger logger = Logger.getLogger(YourEJBClass.class);
  4. use the logger in any method: logger.info("my log");

JBoss already comes with a configuration file under %JBOSS_FOLDER%/standalone/configuration/standalone.xml. By default, your logger will output to server.log and console, but you can add some appender to output your app logs to another file.

Here is an example, edit that file and add the following snippets (following the definition of the file):

  • This one is to add an appender to the file myappfile.log inside the logs folder (add this right after the already defined under name=”FILE”):
     <periodic-rotating-file-handler name="FILETWO">
       <formatter>
         <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
       </formatter>
       <file relative-to="jboss.server.log.dir" path="myappfile.log"/>
       <suffix value=".yyyy-MM-dd"/>
       <append value="true"/>
     </periodic-rotating-file-handler>
  • Add this snippet tells log4j to send all logs from “com.mypackage” category to the previously created appender (copy this right after other defined logger in the file, but before the root-logger):
     <logger category="com.mypackage">
         <level name="DEBUG"/>
         <handlers>
             <handler name="CONSOLE"/>
             <handler name="FILETWO"/>
         </handlers>
     </logger>

Restart the server and you should see the new myappfile.log in the folder. Make sure your app logs something, for example, adding logger.info(“my servlet info log”) in some servlet and call it from the browser. You’ll also see this log in the console

If you need further customization, have a look at log4j help.

Using LdapExtLoginModule with JaasSecurityDomain (securing passwords)

In my last post I wrote about how to connect a JBoss to LDAP defining an LdapExtLoginModule. Clearly, as suggested by the comment of Terry, the password in the xml is in plain text. In this post I’ll explain how to secure this password.

This is really easy to do as suggested in the JBoss docs, just add the following xml to the file $JBOSS_HOME/server/$PROFILE/conf/jboss-service.xml, which will add a JaasSecurityDomain bean to the jmx-console, which will be available for encrypting passwords in Base64:

  <mbean code="org.jboss.security.plugins.JaasSecurityDomain"
      name="jboss.security:service=JaasSecurityDomain,domain=jmx-console">
      <constructor>
         <arg type="java.lang.String" value="jmx-console"></arg>
      </constructor>
      <attribute name="KeyStorePass">some_password</attribute>
      <attribute name="Salt">abcdefgh</attribute>
      <attribute name="IterationCount">66</attribute>
   </mbean>

After this, start the JBoss server and navigate to the JMX Console (http://localhost:8080/jmx-console/ by default) and select the org.jboss.security.plugins.JaasSecurityDomain MBean.

On the org.jboss.security.plugins.JaasSecurityDomain page, look for the encode64(String password) method. Pass the plain text version of the password being used by the LdapExtLoginModule to this method, and invoke it. The return value will be the encrypted version of the password encoded as Base64.

After this, open login-config.xml, edit the LdapExtLoginModule created previously, replacing the password with the encrypted one and tell the module that the password is in encrypted form. The policy should look have the following lines (adding the jaasSecurityDomain option and editing the bindCredential):

   <module-option name="jaasSecurityDomain">jboss.security:service=JaasSecurityDomain,domain=jmx-console</module-option>
   <module-option name="bindCredential">6gf.s7eQiJi</module-option> <!-- LDAP password:  -->

Restart the server and that’s it!

As we see, in this case, the keystore password is still as plain text in the jboss-service.xml file, but this password can be stored in a secure location, for example, using a keystore, as suggested in: https://community.jboss.org/wiki/JBossAS7SecuringPasswords

Authenticate JBoss application using JAAS and LDAP

It is very easy to connect a JBoss to an LDAP server and creating Java EE applications that use the LDAP information for authorization and authentication. Following these simple steps you will be able to configure your JBoss and a web application (configuring an ejb deployment is similar, just read the Java EE API to map the attributes from web.xml to ejb annotations).

For this example I already have an Apache Directory Server running locally, with the sample LDIF with the sevenSeas company imported. You can find the file and tutorial in the Apache DS documentation.

There are two main steps to be able to use LDAP as an authentication mechanism:

  1. Configure JBoss to connect to LDAP server
  2. Configure the application to use the application policy

Configure JBoss to connect to LDAP server

The JBoss connects to the LDAP server using an application-policy, which is configured in %server_path%/conf/login-config.xml
Just add the following entry in the login-config.xml. You can see the description of the important attributes:

  <application-policy name="ApacheDS">
   <authentication>
   <login-module code="org.jboss.security.auth.spi.LdapExtLoginModule" flag="required" >
   <module-option name="java.naming.factory.initial">com.sun.jndi.ldap.LdapCtxFactory</module-option>
   <module-option name="java.naming.provider.url">ldap://localhost:10389</module-option> <!-- LDAP url-->
   <module-option name="java.naming.security.authentication">simple</module-option>
   <module-option name="bindDN">uid=admin,ou=system</module-option> <!-- LDAP user to connect -->
   <module-option name="bindCredential">secret</module-option> <!-- LDAP password -->
   <module-option name="baseCtxDN">ou=people,o=sevenSeas</module-option>
   <module-option name="baseFilter">(uid={0})</module-option>

   <module-option name="rolesCtxDN">ou=groups,o=sevenSeas</module-option> <!-- context where to search for groups -->
   <module-option name="roleFilter">(uniquemember={1})</module-option> <!-- filter, this searches for groups which have the user set in the attribute 'uniquemember' -->
   <module-option name="roleAttributeID">cn</module-option>
   <module-option name="searchScope">SUBTREE_SCOPE</module-option> <!-- Search for groups in all subtrees -->
   <module-option name="roleRecursion">0</module-option> <!-- how many levels to search recursively inside a group for a user  -->
   <module-option name="allowEmptyPasswords">true</module-option>
   </login-module>
   </authentication>
  </application-policy>

As you can see, the bindCredential is not encrypted. In order to do so, you can check out my post about securing the LdapExtLoginModule

Configure the web application to use the application policy

First, we need to connect the java web application to the application policy defined in JBoss. In order to do this, you need to create the file jboss-web.xml in the WEB-INF folder, the same folder where the web.xml resides.
Here is the content of the file (this works for JBoss 5 in a windows machine, you may need to change the header of the file):

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE jboss-web
    PUBLIC "-//JBoss//DTD Web Application 2.3V2//EN"
    "http://www.jboss.org/j2ee/dtd/jboss-web_3_2.dtd">

<jboss-web>
  <security-domain>java:/jaas/ApacheDS</security-domain>
</jboss-web>

This will tell the container to use the ApacheDS application-policy we defined previously in JBoss.

After this, we only need to restrict the specific urls or servlets to certain roles. In this example, we will only allow access for users in the group “HMS Bounty”, otherwise a 403 (forbidden) will be issued.
In order to do this, we need to edit the web.xml file, adding the following configuration:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.5"
 xmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 <servlet>
  <servlet-name>AServlet</servlet-name>
  <servlet-class>com.app.AServlet</servlet-class>
 </servlet>
 <servlet-mapping>
  <servlet-name>AServlet</servlet-name>
  <url-pattern>/AServlet</url-pattern> 
 </servlet-mapping>
 
 <!-- ... more servlets and config ...-->
 
 <security-constraint>
  <display-name>All resources</display-name>
  <web-resource-collection>
   <web-resource-name>All resources</web-resource-name>
   <url-pattern>/*</url-pattern>
  </web-resource-collection>
  <auth-constraint>
   <role-name>HMS Bounty</role-name>
  </auth-constraint>
 </security-constraint>
 <login-config>
  <auth-method>BASIC</auth-method>
 </login-config>

</web-app>

Following this example, you can restrict access to different resources to other roles.

Configure an EJB based WS to use the application policy

If, in turn, you want to secure an EJB based WS, just adding these annotations at the start of the implementing class will do:

@org.jboss.wsf.spi.annotation.WebContext(contextRoot="MyCtxRoot" , authMethod = "BASIC", secureWSDLAccess = false)
@org.jboss.ejb3.annotation.SecurityDomain( "java:/jaas/ApacheDS" )
@RolesAllowed("HMS Bounty")
public class MyWSImplementation implements MyWSInterface{
...

Access EJB 3.0 in JBoss 5, from JBoss 4 – java.lang.ClassCastException

If you are in a process of migrating JBoss servers you may sometimes need to deploy an EAR in a newer server, while having othres in the older servers, and keep the integration between the apps. I faced this issue when migrating from JBoss 4.3 to JBoss 5, but you may face a similar issue when migrating different versions.

One problem that may arrive when an application in the older server (JBoss 4) tries to access an EJB in the newer (JBoss 5) is this exception when doing a lookup:
java.lang.ClassCastException: javax.naming.Reference cannot be cast to XXX
Being XXX the interface you want to lookup in the JBoss 5 server.

This problem occurs because the application is using by default the client libraries of the JBoss 4 server. To solve this problem, you need to add the client jar files of the JBoss 5 server to the application in JBoss 4.
In order to do this, you need to copy the jars from JBoss 5 jbossall-client.jar and all its dependencies (listed in the META-INF, excluding jnp-client.jar) inside the application EAR file in JBoss 4 (in the lib folder inside the EAR).

This is the full list of jar files that need to be copied from /jboss-as/client inside /lib:
common-annotations.jar
commons-beanutils.jar
commons-collections.jar
commons-digester.jar
commons-logging.jar
concurrent.jar
ejb3-persistence.jar
hibernate-annotations.jar
hibernate-commons-annotations.jar
hibernate-core.jar
hibernate-validator.jar
jboss-aop-client.jar
jboss-appclient.jar
jboss-aspect-jdk50-client.jar
jboss-client.jar
jboss-common-core.jar
jboss-deployers-client-spi.jar
jboss-deployers-client.jar
jboss-deployers-core-spi.jar
jboss-deployers-core.jar
jboss-deployment.jar
jboss-ejb3-common-client.jar
jboss-ejb3-core-client.jar
jboss-ejb3-ext-api-impl.jar
jboss-ejb3-ext-api.jar
jboss-ejb3-proxy-clustered-client.jar
jboss-ejb3-proxy-impl-client.jar
jboss-ejb3-proxy-spi-client.jar
jboss-ejb3-security-client.jar
jboss-ha-client.jar
jboss-ha-legacy-client.jar
jboss-iiop-client.jar
jboss-integration.jar
jboss-j2se.jar
jboss-javaee.jar
jboss-jsr77-client.jar
jboss-logging-jdk.jar
jboss-logging-log4j.jar
jboss-logging-spi.jar
jboss-mdr.jar
jboss-messaging-client.jar
jboss-profileservice-client.jar
jboss-remoting.jar
jboss-security-spi.jar
jboss-serialization.jar
jboss-srp-client.jar
jboss-system-client.jar
jboss-system-jmx-client.jar
jbossall-client.jar
jbosscx-client.jar
jbossjts.jar
jbosssx-as-client.jar
jbosssx-client.jar
jmx-client.jar
jmx-invoker-adaptor-client.jar
jsf-facelets.jar
jsf-tlds.jar
jstl.jar
PagosWebFachada.jar
richfaces-api-3.2.1.GA.jar
richfaces-impl-3.2.1.GA.jar
richfaces-ui-3.2.1.GA.jar
slf4j-api.jar
slf4j-jboss-logging.jar
standard.jar
xmlsec.jar

NOTE: If you fail to copy this list and add also the jnp-client.jar you will get this error when deploying the application:
java.lang.IncompatibleClassChangeError: Class org.jnp.server.NamingServer does not implement the requested interface org.jnp.interfaces.Naming

Getting started with AOP in JBoss 5.1 with a simple example

Introduction

I am writing this post since it took me a while to configure and run my first AOP example in a JBoss application, but I must say after spending some time, I realized it is quite easy, I just couldn’t find a simple example documenting all the needed steps. I hope this post helps you to get quickly started, if that’s the case let me know, or if you ran into other issues. It is always inspiring to read your comments.
In this post I’m not going to introduce Aspect Oriented Programming (AOP), as this is not a recent idea and there are several books you can read. If you need some intro, you can read any of these:

The examples provided in this post will allow you to develop aspects for any class deployed in a JBoss server. If you only want to intercept EJB methods you can use the EJB Interceptors, defined in EJB 3.0. For more info about Interceptors, check out this link and book:

AOP Example in JBoss 5.1

Let’s get started. Reading this link almost did the job, but I still had some things to figure out before everything worked. I also had to take a look at JBoss documentation.
Following these steps you’ll have a very simple and running example of an AOP interceptor which will log calls to methods of a package classes. After having this example up and running, the possibilities are limitless 🙂
I assume you are running with the ‘default’ server configuration. If you use another, you’ll have to ensure you are editing the correct folders (for example, change ‘default’ to ‘all’).

Configure JBoss

  1. Copy the pluggable-instrumentor.jar from the lib/ directory of your JBoss AOP distribution (%JBOSS_PATH%/jboss-as/server/default/deployers/jboss-aop-jboss5.deployer/) to the bin/ directory of your JBoss Enterprise Application Platform.
  2. Edit the startup script of the JBoss server (run.bat or run.sh depending if you are on windows or linux) and add “-javaagent:pluggable-instrumentor.jar” into JAVA_OPTS variable
  3. In case you don’t know, you’ll find this file in %JBOSS_PATH%/jboss-as/bin/.

  4. Edit %JBOSS_PATH%/jboss-as/server/default/conf/bootstrap/aop.xml:
    1. Set the element enableLoadtimeWeaving to “true”
    2. The property will look like

      	<property name="enableLoadtimeWeaving">true</property>
      	
    3. Add to the element include the package you want to instrument or intercept
    4. By default, all packages not listed in the exclude property will be intercepted, so you may skip this step.
      If you choose to explicitly list your package (ie com.mypackage and all subpackages), the include property will look like:

      	<property name="include">org.jboss.test., org.jboss.injbossaop. , com.mypackage. </property>
      	

This is enough to make JBoss run AOP every time you run it with the start scipt. If you want to enable AOP interceptors when running JBoss from Eclipse, you will need to add -javaagent:pluggable-instrumentor.jar to the VM arguments in the server properties.

Logger interceptor

Now, lets build our first AOP interceptor, which will add a log to every call to methods in package and subpackages of com.mypackage.
First, we create an interceptor, a simple Java class which implements org.jboss.aop.advice.Interceptor. In this class we will call invokeNext() to call the original method and log the time taken to run. This is the code:

package com;

import org.apache.log4j.Logger;
import org.jboss.aop.advice.Interceptor;
import org.jboss.aop.joinpoint.Invocation;
import org.jboss.aop.joinpoint.MethodInvocation;

public class LogInterceptor implements Interceptor {

	@Override
	public String getName() {
		return "LogInterceptor";
	}

	static Logger logger = Logger.getLogger(LogInterceptor.class);

	@Override
	public Object invoke(Invocation invocation) throws Throwable {
		long time = System.currentTimeMillis();
		try {
			// NEVER FORGET TO CALL invokeNext()
			// unless you want to cancel the call to the destination method
			// (i.e.: a security interceptor)
			return invocation.invokeNext();
		} finally {
			time = System.currentTimeMillis() - time;
			if (invocation instanceof MethodInvocation) {
				MethodInvocation mi = (MethodInvocation) invocation;
				String clazz = "";
				String method = "";
				try {
					clazz = mi.getTargetObject().getClass().toString();
					method = mi.getMethod().getName();
				} catch (Throwable e) {
					logger.error("Error when trying to get target info");
				}
				logger.info("LogInterceptor: " + time + "ms - class: " + clazz
						+ " method: " + method);
			}
		}
	}
}

After this, we create a jboss-aop.xml which will look like this (we are just defining the interceptor and creating a pointcut, which defines when the interceptor will be called):

<?xml version="1.0" encoding="UTF-8"?>
<aop xmlns="urn:jboss:aop-beans:1.0">
  <interceptor name="Int" class="com.LogInterceptor"/>
  <bind pointcut="execution(* com.mypackage.*->*(..))">
    <interceptor-ref name="Int"/>
  </bind >
</aop>

This defines a pointcut to all methods inside package com.mypackage, no matter their return type or parameters. Later on this post I’ll add some more examples of pointcuts for you to narrow down the list of intercepted methods.

After compiling com.LogInterceptor, we’ll just create a jar file, for example aopExample.jar which will contain these files and folders:

com
	LogInterceptor.class
META-INF
	jboss-aop.xml

After this, copy this jar file into the deploy folder together with your application, restart your jboss server, and after running the application (classes inside com.mypackage) you’ll start seeing these logs in JBoss:

21:59:22,254 INFO  [LogInterceptor] LogInterceptor: 2ms - class: class com.mypackage.Hello method: doGet
22:04:43,637 INFO  [LogInterceptor] LogInterceptor: 0ms - class: class com.mypackage.Hello method: doGet

If you want to quickly test this, you can download my testAop.jar and my test application TestWeb.war and put them in your JBoss server.
Here are the links:
testAop.jar
TestWeb.war

TestWeb.war has only one servlet: com.mypackage.Hello which prints Hello world in the browser. The important part here is that testAop.jar is intercepting calls to TestWeb.war. Just point your browser to http://localhost:8180/TestWeb/Hello and look at the server log.

Starting with this example, you can start doing more complex things with AOP, from logging how long it takes a method to run, to creating a security framework.

Pointcuts

Here are some examples of pointcuts if you want to start playing around with these:

  • <bind pointcut=”execution(* com.mypackage.*->*(..))”>
  • Will intercept any method call inside the package com.mypackage.

  • <bind pointcut=”execution(* com.mypackage.MyClass->*(..))”>
  • Will intercept any method call to the class com.mypackage.MyClass

  • <bind pointcut=”execution(* com.mypackage.MyClass->myMethod(..))”&gt
  • Will intercept the method myMethod (with any combination of parameters and return type) in class MyClass .

Interceptor API

When developing an interceptor, you can use the API to access important information regarding the intercepted invocation. You can change the original parameters of the invocation, change the return value, and have access to the destination (class and method) information.

At the invoke(Invocation mi) method, if Invocation is instance of MethodInvocation you can call:

mi.getTargetObject().getClass() to get the intercepted class intercepted.

mi.getMethod().getName() to get the method name which is being intercepted.