Buscar este blog

domingo, 17 de enero de 2016

JBoss - Datasources and JNDI aliases

Almost all web app requires access to a database. This is done by creating a datasource object in the server and by making it accessible to the apps by using its JNDI references.
So, when you want to deploy a new web app in your server, you usually do the following steps:
  1. Declare a new Datasource (or XA-Datasource) in the server wich points to the database
  2. Configure the web app to lookup the JNDI entry in which you declare the Datasource

Cool. But you may find yourself in some situations when this may not be the best solution. I´m thinking in two scenarios:
  1. Multiple web apps access to the same database
  2. One web app wishes to switch between databases in the same environment

The solution is to use JNDI aliases. This allows you to use one JNDI entry which, in turns, returns the value of another JNDI, just like a proxy.
As JBoss doc states (https://docs.jboss.org/author/display/AS71/JNDI+Reference), three different types of bindings are supported:
  • Simple - A primitive or string.
  • ObjectFactory - This allows to specify the javax.naming.spi.ObjectFactory that is used to create the looked up value.
  • Lookup - This allows to create JNDI aliases. When this entry is looked up, it will lookup the target and return the result.

This is an example of use of the lookup binding type:
/subsystem=naming/binding="java:/alias/datasource":add(binding-type=lookup, lookup="java:jboss/datasources/pruebas")
/subsystem=naming/binding="java:/alias/datasource":read-attribute(name=lookup)

(...)

/subsystem=naming/binding="java:/alias/datasource":write-attribute(name=lookup,value="java:jboss/datasources/pruebas2")
:reload

Here I assume that there are two datasources previously created, accesibles in java:jboss/datasources/pruebas2 and java:jboss/datasources/pruebas2. First I created a new JNDI which points to the first one and then update its value to the second one.


Now I will analyze more in deep the two scenarios presented.

Multiples web apps access to the same database

Suppose you have have multiple web apps who need to access to the same database (yes, this is not a good architecture, but imagine that for some legacy reasons they have to). In the future each app would access to its own database, so you configure them to use a different datasource.

What you would do is to create multiple datasources in your server, all of them pointing to the same database. But if the database location changes, for example the IT department decides to move them to a new server, you must to reconfigure all datasources to point to this new location.

By using multiple JNDI entries with binding lookup type you can configure just one datasource and reference it from multiple JNDI keys.

One web app wishes to switch between databases in the same environment

The other scenario could be when you have a single web app and multiple database environments. For example, you have two databases in your Test environment and you want to switch between then in order to make different tests. Again, the best solution is to have multiple full environments and deploy your app in each one, but this is not a ideal world.

What you would do is to create multiple datasources in your server, each one pointing to one different database. But you also need to reconfigure your web app each time you want to switch between them.

By using a single JNDI entry with binding lookup type you can configure your app to pick the datasource from it, and internally reference the desired datasource.


Note. I found a great post about JNDI use in http://middlewaremagic.com/jboss/?p=1690

sábado, 9 de enero de 2016

Maven jaxb2 plugin - Generate class from XSD Schema with custom bindings file

In a previous post (http://trabajosdesisifo.blogspot.com.es/2015/04/generate-classes-from-xsd-xmlrootelement.html) I talked about how to generate java classes from XSDs and WSDLs files. When I worked with XSD Schema files I was using org.jvnet.jaxb2.maven2 / maven-jaxb2-plugin, now I post the equivalent with org.codehaus.mojo / maven-jaxb2-plugin a newer version.

My XSD and XJB files are located under /src/main/resources/META-INF/xsd/consultaVersion directory.
File consultaVersion.xsd:
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="aplicacion">
    <xs:complexType>
      <xs:sequence>
        <xs:element type="xs:string" name="nombre"/>
        <xs:element type="xs:string" name="version"/>
        <xs:element type="xs:date" name="fecha"/>
        <xs:element type="xs:string" name="observaciones"/>
        <xs:element type="xs:anyURI" name="urlDescarga"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

File bindings.xjb:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings version="2.1" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">

 <jaxb:globalBindings generateIsSetMethod="true" localScoping="toplevel">
  <jaxb:javaType name="java.util.Calendar" xmlType="xs:dateTime" parseMethod="javax.xml.bind.DatatypeConverter.parseDateTime" printMethod="javax.xml.bind.DatatypeConverter.printDateTime" />
 </jaxb:globalBindings>


 <jaxb:bindings schemaLocation="consultaVersion.xsd" node="/xs:schema">
  <jaxb:schemaBindings>
   <jaxb:package name="es.sisifo.myproject.framework.service.versionado.dto" />
  </jaxb:schemaBindings>
 </jaxb:bindings>

</jaxb:bindings>

Note that with this binding file dateTime fields are converted to java Calendar type.

And this is my pom.xml:
<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/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>es.sisifo.myproject</groupId>
 <artifactId>desktop-framwork</artifactId>
 <version>0.0.1-SNAPSHOT</version>

 <properties>
  (...)
  <java.version>1.7</java.version>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 </properties>

 <build>
  <pluginManagement>
   <plugins>
    <!--This plugin's configuration is used to store Eclipse m2e settings 
     only. It has no influence on the Maven build itself. -->
    <plugin>
     <groupId>org.eclipse.m2e</groupId>
     <artifactId>lifecycle-mapping</artifactId>
     <version>1.0.0</version>
     <configuration>
      <lifecycleMappingMetadata>
       <pluginExecutions>
        <pluginExecution>
         <pluginExecutionFilter>
          <groupId>
           org.codehaus.mojo
          </groupId>
          <artifactId>
           jaxb2-maven-plugin
          </artifactId>
          <versionRange>
           [2.2,)
          </versionRange>
          <goals>
           <goal>xjc</goal>
          </goals>
         </pluginExecutionFilter>
         <action>
          <ignore></ignore>
         </action>
        </pluginExecution>
       </pluginExecutions>
      </lifecycleMappingMetadata>
     </configuration>
    </plugin>
   </plugins>
  </pluginManagement>

  <plugins>
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.3</version>
    <configuration>
     <target>${java.version}</target>
     <source>${java.version}</source>
    </configuration>
   </plugin>
  
  
   <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>jaxb2-maven-plugin</artifactId>
    <version>2.2</version>
    <executions>
     <execution>
      <id>Generate-clases-xsd</id>
      <phase>generate-sources</phase>
      <goals>
       <goal>xjc</goal>
      </goals>
     </execution>
    </executions>
    <configuration>
     <outputDirectory>${basedir}/target/xjc/generated</outputDirectory>
     <sources>
      <source>${basedir}/src/main/resources/META-INF/xsd/consultaVersion/consultaVersion.xsd</source>
     </sources>
     <xjbSources>
      <xjbSource>${basedir}/src/main/resources/META-INF/xsd/consultaVersion/bindings.xjb</xjbSource>
     </xjbSources>
     <target>2.1</target>
     <generateEpisode>false</generateEpisode>
     <encoding>${project.build.sourceEncoding}</encoding>      
    </configuration>
   </plugin>
  </plugins>

 </build>

 <dependencies>
  (... Nothing special ...)
 </dependencies>
</project>


Aditional info:

sábado, 2 de enero de 2016

JBoss - EJB - java.lang.ClassCastException: org.xnio.SingleOption cannot be cast to org.xnio.Option

This exception is thrown during a Context.lookup() in order to get a remote EJB in JBoss EAP 6.x
18:20:10,906 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/ejemplo].[spring]] (http-localhost/127.0.0.1:8080-3) JBWEB000236: Servlet.service() for servlet spring threw exception: java.lang.ClassCastException: org.xnio.SingleOption cannot be cast to org.xnio.Option
 at org.xnio.Option.fromString(Option.java:155) [xnio-api-3.0.7.GA.jar:3.0.7.GA]
 at org.xnio.OptionMap$Builder.parseAll(OptionMap.java:316) [xnio-api-3.0.7.GA.jar:3.0.7.GA]
 at org.jboss.ejb.client.PropertiesBasedEJBClientConfiguration.getOptionMapFromProperties(PropertiesBasedEJBClientConfiguration.java:234) [jboss-ejb-client-1.0.24.Final-redhat-1.jar:1.0.24.Final-redhat-1]
 at org.jboss.ejb.client.PropertiesBasedEJBClientConfiguration.parseProperties(PropertiesBasedEJBClientConfiguration.java:221) [jboss-ejb-client-1.0.24.Final-redhat-1.jar:1.0.24.Final-redhat-1]
 at org.jboss.ejb.client.PropertiesBasedEJBClientConfiguration.<init>(PropertiesBasedEJBClientConfiguration.java:118) [jboss-ejb-client-1.0.24.Final-redhat-1.jar:1.0.24.Final-redhat-1]
 at org.jboss.ejb.client.naming.ejb.EjbNamingContext.createIdentifiableEjbClientContext(EjbNamingContext.java:255) [jboss-ejb-client-1.0.24.Final-redhat-1.jar:1.0.24.Final-redhat-1]
 at org.jboss.ejb.client.naming.ejb.EjbNamingContext.setupScopedEjbClientContextIfNeeded(EjbNamingContext.java:123) [jboss-ejb-client-1.0.24.Final-redhat-1.jar:1.0.24.Final-redhat-1]
 at org.jboss.ejb.client.naming.ejb.EjbNamingContext.<init>(EjbNamingContext.java:98) [jboss-ejb-client-1.0.24.Final-redhat-1.jar:1.0.24.Final-redhat-1]
 at org.jboss.ejb.client.naming.ejb.ejbURLContextFactory.getObjectInstance(ejbURLContextFactory.java:38) [jboss-ejb-client-1.0.24.Final-redhat-1.jar:1.0.24.Final-redhat-1]
 at org.jboss.as.naming.InitialContext.lookup(InitialContext.java:101)
 at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:183)
 at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:179)
 at javax.naming.InitialContext.lookup(InitialContext.java:411) [rt.jar:1.7.0_21]

Solution.

Add the following dependencies to the jboss-deployment-structure.xml:
  • org.jboss.xnio
  • org.jboss.remoting3
  • org.jboss.ejb-client

<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
 <deployment>
  <dependencies>
   <module name="org.jboss.xnio" export="true" />
   <module name="org.jboss.remoting3" export="true" />
   <module name="org.jboss.ejb-client" export="true" />
  </dependencies>
  
  <exclude-subsystems>
   <subsystem name="logging" />
  </exclude-subsystems>

  <exclusions>
   <module name="org.apache.log4j" />
   <module name="org.slf4j" />
   <module name="org.log4j" />
   <module name="org.jboss.logging" />
  </exclusions>
 </deployment>
</jboss-deployment-structure>

miércoles, 30 de diciembre de 2015

Log4j 1.x - Custom ThrowableRenderer

With log4j 1.x you can customize the format of your message logs with EnhancedPatternLayout,
There is a special Conversion Character to customize exception traces called throwable. But if you need more control about how to print exceptions you can hook your own renderer.

Create a class which implements org.apache.log4j.spi.ThrowableRenderer.
package es.cixtec.complexarchetype.web.log4j;

import org.apache.log4j.spi.ThrowableRenderer;

public class MyCustomThrowableRenderer implements ThrowableRenderer {

    @Override
    public String[] doRender(final Throwable t) {
        // do something with t
        return new String[] { "This", "is", "a", "custom", "trace" };
    }
}

Then, in log4j.xml, you need to link this class by using the throwableRenderer tag.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration debug="true"  xmlns:log4j='http://jakarta.apache.org/log4j/'>
    
    <throwableRenderer class="es.sisifo.test.web.log4j.MyCustomThrowableRenderer"/>
    
    <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.EnhancedPatternLayout">
        <param name="ConversionPattern" 
          value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
        </layout>
    </appender>
    
    <appender name="LOG" class="org.apache.log4j.DailyRollingFileAppender">
        <param name="File" value="${jboss.server.log.dir}/test-web.log" />
        <param name="DatePattern" value="'.'yyyy-MM-dd"/>
        <layout class="org.apache.log4j.EnhancedPatternLayout">
            <param name="ConversionPattern" value="[%-5p][%d{ISO8601}][%-4L] %F>%m%n" />
        </layout>
    </appender>
    

    <root>
        <level value="DEBUG" />
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="LOG" />
    </root>

</log4j:configuration>

As result, when a exception is logged you get something like this.
LOGGER.error("Exceptions happens", new NullPointerException());

[ERROR][2015-12-30 11:33:09,003][45  ] GridServiceImpl.java>Exceptions happens
This
is
a
custom
trace

lunes, 28 de diciembre de 2015

JBoss - Useful system properties

This post is a recollection of some magic system properties to tweak JBoss. Some of them were found by our development team while others where found by our customer.
These were tested with JBoss EAP 6.2 and JBoss EAP 6.4.

Some of these properties can be found in the following page: https://docs.jboss.org/jbossweb/7.0.x/sysprops.html. Others are more hidden.

In domain mode, you can add a system property to a server with the following command:
[domain@localhost:9999 /] /host=hostController01/server-config=serv-one/system-property=popertyName:add(value=propertyValue)

Clear JSP cache on context destroy

Used in order to force JBoss to clean all .jsp an .class files during an application redeploy.

Key: DELETE_WORK_DIR_ONCONTEXTDESTROY
Value: true


Set server bind addres

Used in order to set a specific IP to a server when the host machine has multiple network interfaces.

Key 1: jboss.bind.address
Value: any valid address

Key 2: jboss.bind.address.unsecure
Value: any valid address

With these properties, in domain mode, you can multiple servers with different IPs address in the same machine.


Configure default request encoding

Used in order to send data encoded in a particular charset to the server.

Key 1: org.apache.catalina.connector.URI_ENCODING 
value: UTF-8

Key 2: org.apache.catalina.connector.USE_BODY_ENCODING_FOR_QUERY_STRING 
value: true


Configure maximun POST parammeter

Used in order to allow the browser to send a POST with a huge number of parameters, i.e, to submit a form with a lot of fields.

Key: org.apache.tomcat.util.http.Parameters.MAX_COUNT
value: a big number