Buscar este blog

domingo, 29 de noviembre de 2015

JBoss EAP 6.2 Domain - HornetQ Cluster - Configure ConnectionFactory

I need that a standalone client app send messages to a queue in a JBoss EAP 6.X domain. This domain have multiple nodes and, if one of those nodes crash, the client could keep sending messages to the others.

I will try to dig a little deeper in the future, but for now, this is the change I made in the Remote Connection Factory configuration.

<connection-factory name="RemoteConnectionFactory">   
 <discovery-group-ref discovery-group-name="dg-group1"/>
 <entries>
  <entry name="java:jboss/exported/jms/RemoteConnectionFactory"/>
 </entries>
 <ha>true</ha>
 <block-on-acknowledge>true</block-on-acknowledge>
 <retry-interval>1000</retry-interval>
 <retry-interval-multiplier>1.0</retry-interval-multiplier>
 <reconnect-attempts>-1</reconnect-attempts>
</connection-factory>

The key is to reference the discovery group instead the connector.

And here the CLI:
/subsystem=messaging/hornetq-server=default/connection-factory=RemoteConnectionFactory:add(discovery-group-name=dg-group1, entries= ["java:jboss/exported/jms/RemoteConnectionFactory"], ha=true, block-on-acknowledge=true, retry-interval=1000, retry-interval-multiplier=1.0, reconnect-attempts=-1)

Java Web Start - Found unsigned entry in resource

When you launch a Java Web Start application via JNLP file (check here https://java.com/en/download/faq/java_webstart.xml) there are a lot of security issues you have to keep in mind. Among them is the fact that your jar must be signed in order to Java allow it to be executed.

If your jar is not signed you will get some message like this:
com.sun.deploy.net.JARSigningException: Se ha encontrado una entrada sin firma en el recurso: https://desarr.local/jnlp/XXXXXXX-jar-with-dependencies.jar


I built my jar by using Maven, and the final output is a file called XXXX-0.0.1-SNAPSHOT-jar-with-dependencies.jar. This jar contains all third party classes and resources that my application need to work.
<plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-assembly-plugin</artifactId>
 <version>2.6</version>
 <executions>
  <execution>
   <id>make-assembly</id>
   <phase>package</phase>
   <goals>
    <goal>single</goal>
   </goals>
   <configuration>
    <archive>
     <manifest>
      <mainClass>xxxxxxxxxx.Main</mainClass>
     </manifest>
     <manifestEntries>
      <Permissions>all-permissions</Permissions>
      <Codebase>desarr.local</Codebase>
      <Application-Name>xxxxxxxxx</Application-Name>
      <Application-Library-Allowable-Codebase>https://desarr.local</Application-Library-Allowable-Codebase>
      <Entry-Point>xxxxxxxxxx.Main</Entry-Point>
      <Built-By>Sisifo</Built-By>
     </manifestEntries>
    </archive>
    <descriptorRefs>
     <descriptorRef>jar-with-dependencies</descriptorRef>
    </descriptorRefs>
   </configuration>
  </execution>
 </executions>
</plugin>

Note. 
  • I hid the application name on purpose because it is a real application I am working with.
  • I downloaded the application from a Apache server located in "desarr.local", i.e, this is my htdocs basedir.

So I just needed to sign a jar. Fine, no more than five minutes, thats very easy with jarsigner tool (check here https://docs.oracle.com/javase/7/docs/technotes/tools/windows/jarsigner.html).


To sign my jar I created a self-signed certificate acting as a CA, and with it, I signed a second certificate (kind pro eh).
So, I have a PKCS12 certificate called jar-signer signed with my CA:
  • The file is "jar_signer(1234).p12"
  • The file format is PKCS12
  • The password file is "1234"
  • The certificate alias is "jar-signer"
  • The alias key is "1234"



With this I now could sign my jar:
"c:\Program Files\Java\jdk1.7.0_21\bin\jarsigner.exe" -keystore jar_signer(1234).p12 -storetype PKCS12 -storepass 1234 -keypass 1234 XXXX-SNAPSHOT-jar-with-dependencies.jar jar-signer

Ok, I have a signed jar. I launch my JNLP file again and... Fail. I still get the exact same error.
The jar was signed properly. By using the "-verify" option of jarsigner I got success verification (although with some warnings), but the jar was fine.
"c:\Program Files\Java\jdk1.7.0_21\bin\jarsigner.exe" -verify XXXX-0.0.1-SNAPSHOT-jar-with-dependencies.jar
jar verified.

Warning:
This jar contains entries whose certificate chain is not validated.

Re-run with the -verbose and -certs options for more details.

At this point I checked the following issues:
1) My self signed certificates were not suitable.
I passed the jar to our client and they signed it with a "true" certificate,.
Result: Fail.

2) There were problems with the jarsigner tool.
I signed the jar with the jarsigner shipped with JDK 1.6.0_45, 1.7.0_21 and 1.8.0_51.
Result: Fail

3) Set to checked the java option to "keep temporary files on my computer"
In Control Panel > Java > General > Temporary files > Configuration.
Result: Fail

4) Import the sign certificate and the CA as trusted for java.
In Control Panel > Java > Security > Manage Certificates > User
Result: Fail

So I was quite sure that my configuration was fine and that the problem should be in the dam jar.

I opened the jar and I saw that there were a lot of non essential files in it, like licenses, poms, READMEs, etc...



I decided to manually remove all this "crap" and sign again. The result... Success!!!

After a while doing try-error deletes I found that the real problem was related to the file called "\jboss-as-jms-client-bom-7.3.0.Final-redhat-14.pom". Check the previous image and you will note that there is a slash "\" in this name. I think that, for some unknown reason, the java launcher was not able to process properly that file or that this file was not well signed at all.


Well, once I found the root of the problem, the next step was to modify the procedure I was using to create the jar.

The maven-assembly-plugin (check here http://maven.apache.org/plugins/maven-assembly-plugin/) has a config option called "descriptors" to reference an external descriptor file. Based on this file, the plugin know how to build the jar.
There are four predefined descriptors, being jar-with-dependencies just one of them.

I changed the plugin configuration and created a custom descriptor.
<plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-assembly-plugin</artifactId>
 <version>2.6</version>
 <executions>
  <execution>
   <id>make-assembly</id>
   <phase>package</phase>
   <goals>
    <goal>single</goal>
   </goals>
   <configuration>
    <archive>
     <manifest>
      <mainClass>xxxxxxxxxx.Main</mainClass>
     </manifest>
     <manifestEntries>
      <Permissions>all-permissions</Permissions>
      <Codebase>desarr.local</Codebase>
      <Application-Name>xxxxxxxxxx</Application-Name>
      <Application-Library-Allowable-Codebase>https://desarr.local</Application-Library-Allowable-Codebase>
      <Entry-Point>xxxxxxxxxx.Main</Entry-Point>
      <Built-By>Sisifo</Built-By>
     </manifestEntries>
    </archive>
    <descriptors>
     <descriptor>src/dev/assembly/distribution.xml</descriptor>
    </descriptors>
   </configuration>
  </execution>
 </executions>
</plugin>

And this is my distribution.xml file:
<assembly
 xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
 <id>jar-with-dependencies</id>
 <formats>
  <format>jar</format>
 </formats>
 <includeBaseDirectory>false</includeBaseDirectory>
 <dependencySets>
  <dependencySet>
   <outputDirectory>/</outputDirectory>
   <useProjectArtifact>true</useProjectArtifact>
   <unpack>true</unpack>
   <scope>runtime</scope>
   <unpackOptions>
    <excludes>
     <exclude>**/README</exclude>
     <exclude>**/LICENSE</exclude>
     <exclude>**/NOTICE</exclude>
     <exclude>**/ASL2.0</exclude>
     <exclude>**/INDEX.LIST</exclude>
     <exclude>**/*.txt</exclude>
     <exclude>**/*.html</exclude>
     <exclude>**/.project</exclude>
     <exclude>**/.classpath</exclude>
     <exclude>jboss-as-checkstyle/*</exclude>
     <!-- Eclsuiones relacionadas con maven -->     
     <exclude>META-INF/maven/**</exclude>
     <exclude>**/pom.xml</exclude>
     <exclude>**/pom.properties</exclude>
     <exclude>*.pom</exclude>
     <exclude>**/*.pom</exclude>
     <!-- Licencias -->
     <exclude>META-INF/licenses/*</exclude>
     <exclude>licenses/*</exclude>
     
          
     <exclude>%regex[jboss-as-jms-client-bom]</exclude>
     <exclude>\jboss-as-jms-client-bom-7.3.0.Final-redhat-14.pom</exclude>
    </excludes>
   </unpackOptions>
  </dependencySet>
 </dependencySets>

With this configuration what I was trying to do was to remove all non-essential files and, specifically, the jboss-as-jms-client-bom-7.3.0.Final-redhat-14.pom.
Result: Fail
Even doing so, this file was still there. I tried all kind of expressions, excludes, fieldsets, etc... but no luck.


So, the plan B was to use a ant task to open the jar file, remove the file, and repack it.
For this I used maven-antrun-plugin.
<plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-antrun-plugin</artifactId>
 <version>1.7</version>
 <executions>
  <execution>
   <id>elimina-bom</id>
   <phase>package</phase>
   <goals>
    <goal>run</goal>
   </goals>
   <configuration>
    <tasks>        
     <zip file="${project.build.directory}/${project.build.finalName}-limpio.jar">
      <zipfileset src="${project.build.directory}/${project.build.finalName}-jar-with-dependencies.jar">
       <exclude name="**/*.pom" />
      </zipfileset>          
     </zip>
    </tasks>
   </configuration>
  </execution>
 </executions>
</plugin>

Finally, after long hours of failures, my JNLP app was working...

domingo, 8 de noviembre de 2015

Externalize log4j configuration file in webapp with spring config property

In a previous post (Externalize log4j configuration file in webapp) I explained how to externalize log4j.xml file by using org.springframework.util.Log4jConfigurer inside web.xml. This solution has a drawback, and it's that you need to use a system property wich points to the external file.

In most cases it is more suitable to have a property inside a config file, just like the rest o properties used in the app. This is accomplished with org.springframework.beans.factory.config.MethodInvokingFactoryBean. This class is able to invoke a method of another class, i.e, Log4jConfigurer and you can do it after your config file would be loaded.

The complete solution would be as follow:
<context:property-placeholder properties-ref="properties" order="1" />
<bean id="properties"  class="org.springframework.beans.factory.config.PropertiesFactoryBean">
 <property name="locations">
  <list>
   <value>classpath:conf.properties</value>
  </list>
 </property>
</bean>



<bean id="log4jInitializer" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" depends-on="properties">
 <property name="targetClass" value="org.springframework.util.Log4jConfigurer" />
 <property name="targetMethod" value="initLogging" />
 <property name="arguments">
  <list>
   <value>${customProperty.log4j.location:classpath:log4j.xml}</value>   
  </list>
 </property>
</bean>

Java - Maven - Auto generate setter code for transformers class

I´ve been working with multi layered web applications for the last six years, and one thing I learned is that isolation is a fundamental concept. Each layer should only work with its own objects and should only know about objects of immediate next layer.
This is done by using DTOs (Data Transfer Objects) and transformers classes which convert between them. Usually the objects would have the same fields in different layers, over all if you are starting a project from scratch.

For example, suppose you have a class called UsuarioEntity in your Persistence Layer and a class Called Usuario in your Business Layer.
@Entity
@Table(name="USUARIO")
public class UsuarioEntity {
 @Id @GeneratedValue
 private Long id;

 private String nombre;

 private String nif;

 private String login;

 private String password;

 private Date fechaRegistro;

 private Boolean estaActivo;

 @ManyToOne(fetch=FetchType.EAGER)
 @JoinColumn(name="idTipo")
 private TipoUsuarioEntity tipo = new TipoUsuarioEntity();

(...)
}

public class Usuario {
 private Long id;
 private String nombre;
 private String nif;
 private String login;
 private String password;
 private Date fechaRegistro;
 private Boolean estaActivo;
 private TipoUsuario tipo = new TipoUsuario();

(...)
}

The class responsible for transform between UsuarioEntity and Usuario would receive a object UsuarioEntity and would return a object Usuario.

One option could be use Apache Commons BeanUtils.copyProperties (https://commons.apache.org/proper/commons-beanutils/javadocs/v1.8.3/apidocs/index.html) but I don't  like much because errors appear in runtime. If you change some property in Usuario, you would not notice until run the program.

So I prefer to use the setter/getter option, which leads to code like this:
public Usuario usuarioEntity2Usuario(UsuarioEntity usuarioEntity) {
 Usuario usuario = new Usuario();
 
 //bored setter and getter here
  
 return usuario;
}

But this is a tedious task, more tedious the more classes you have.
What I made was a java snippet that, by reflection, generates thesesetters using one of the classes involved. This is valid only when both classes are quite similar.
public class SetterGetterGeneratorServiceImpl implements SetterGetterGeneratorService {

    @Override
    public String generateSetters(final Class<?> clazz, final String objectSet, final String objectGet) {
        final StringBuilder codigoJava = new StringBuilder();

        for (final Method method : clazz.getDeclaredMethods()) {
            if (method.getName().startsWith("set")) {
                codigoJava.append(objectSet).append(".").append(method.getName()).append("(").append(objectGet)
                        .append(".").append(convertSetEnGet(method.getName())).append("()").append(");\n");
            }
        }

        return codigoJava.toString();
    }


    private String convertSetEnGet(final String methodSetName) {
        return "get" + methodSetName.substring(3);
    }
}

When you call this method with your object class, the name of the object to make the setter and the name of the object to make de getter, you "almost" get the java code you need for your transformer.
codigo = setterGetterGeneratorService.generateSetters(Usuario.class, "usuario", "usuarioEntity");

usuario.setId(usuarioEntity.getId());
usuario.setPassword(usuarioEntity.getPassword());
usuario.setEstaActivo(usuarioEntity.getEstaActivo());
usuario.setFechaRegistro(usuarioEntity.getFechaRegistro());
usuario.setNombre(usuarioEntity.getNombre());
usuario.setNif(usuarioEntity.getNif());
usuario.setLogin(usuarioEntity.getLogin());
//usuario.setTipo(usuarioEntity.getTipo());


Going one step further, I put this code in a Maven plugin so you can invoke it from command line. The  project is in GitHub: https://github.com/evazquezma/maven.

To use this Plugin, you need to configure it in the pom file, and set the dependencies with your project classes, so it will can access your entity and business classes.
<build>
 <plugins>
  <plugin>
   <groupId>es.sisifo.plugins</groupId>
   <artifactId>code-generator</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <dependencies>
    <dependency>
     <groupId>(...)</groupId>
     <artifactId>(...)</artifactId>
     <version>(...)</version>
    </dependency>    
   </dependencies>
  </plugin>
 </plugins>
</build>

To launch de plugin just:
mvn code-generator:setter-getter -DclassName=xxxxxx.Usuario -DobjectSet=usuario -DobjectGet=usuarioEntity

miércoles, 4 de noviembre de 2015

Open SQL Server trace files - RML Utilities

In SQL Server, trace files are generated by SQL Server Profiler.
Microsoft SQL Server Profiler is a graphical user interface to SQL Trace for monitoring an instance of the Database Engine or Analysis Services. You can capture and save data about each event to a file or table to analyze later. For example, you can monitor a production environment to see which stored procedures are affecting performance by executing too slowly. 
Recently we ran with some issues with a web application which uses SQL Server as database. In order to try to analyze what was happening we received a TRC or Trace file, which was generated during a test.

My first try to open this kind of files was ClearTrace, but after a while I was not able to get much insight about the file. The program works fine and you can check some bulk information, but I needed a more fine grain.

Finally I found RML Utilities for SQL Server (RML stands for Replay Markup Language):
The RML utilities allow you to process SQL Server trace files and view reports showing how SQL Server is performing. For example, you can quickly see:
  • Which application, database or login is using the most resources, and which queries are responsible for that
  • Whether there were any plan changes for a batch during the time when the trace was captured and how each of those plans performed
  • What queries are running slower in today's data compared to a previous set of data
When you install RML Utilities (from here), you install several tools (extracted from RML Help):
ReadTrace
ReadTrace consumes as input trace (.TRC) or (.XEL)files and .CAB or .ZIP files which contain .TRC files. The outputs from ReadTrace can be .TRC files, .RML files and the Performance Analysis (PerfAnalysis) database. (A populated performance analysis database is required for Reporter functionality.)
Reporter
Reporter is a .NET based application used for visualizing the trace data loaded by ReadTrace. Reporter displays Reporting Services based report (.rdlc) files by using the client Report Viewer control. A Reporting Services installation is not required. . The report-based infrastructure allows for interactive analysis that was not possible using the static .HTM output from prior versions.
Reporter is compiled for native use on ANY platform. When you review large data sets it is helpful to use larger 64 bit computers.
Ostress
    OStress is a scalable, ODBC based application which can stress or replay database commands. In stress mode you can specify a query via a command line parameter, .SQL script or .RML file. Replay mode uses .RML files generated by ReadTrace as it processes SQL Server trace files.
    ORCA
    OStress Replay Control Agent (ORCA.exe) is a singleton COM object that provides session tracking, sequencing, delta timing and DTC transactional control for OStress replay. 
    OStress handles the ORCA object creation and configuration unless you are performing a multiple instance replay.


    In this case, to open trace files, you only need ReadTrace and Reporter. ReadTrace parses the TRC file and "moves" it into a SQL Server Database called PerfAnalysis (it's can be configured). Then, Reporter opens this Database, interprets this information, and shows it in a user friendly way.

    So, starting with the TRC file, you have to execute de following command:
    ReadTrace -ImySQLTrace.trc -omyOutputDir
    

    I just needed specify the input file and the output dir because in my PC there is already a SQL Server installed. ReadTrace will use windows auntenthicantion to connect to it and it will create the PerfAnalysis database.

    Once executed, Reporter will open automatically. If dont, you can start it manually.




    I leave the funny part, interpret the data, for future posts :)

    domingo, 1 de noviembre de 2015

    org.hsqldb.HsqlException: data exception: string data, right truncation

    This exception appear when you try to populate a database with DBUNIT, and there is one text field which content bigger than the column size. (I spent almost 30 minutes until I realized it...)

    The solution is to increase the column size in the entity mapping.

    As you can see, I had a column named T_EXPED with length 2, and I tried to put in it a string with lenght 3.

    Entity mapping:
    @Entity
    @Table(name="INDDO")
    public class Inddo {
     (...)
     
     @Column(name="T_EXPED", columnDefinition="char(2)")
     private String tipoExpediente;
     
     (...)
    }
    

    DBUNIT file:
    <?xml version='1.0' encoding='UTF-8'?>
    <dataset>
     <INDDO (...) T_EXPED="22I" (...) />
    </dataset>
    

    Full exception trace:
    org.dbunit.DatabaseUnitException: Exception processing table name='INDDO'
     at org.dbunit.operation.RefreshOperation.execute(RefreshOperation.java:130)
     at es.cixtec.entradadocumentos.persistencia.facade.TestIndiceFacade.setup(TestIndiceFacade.java:69)
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
     at java.lang.reflect.Method.invoke(Method.java:601)
     at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
     at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
     at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
     at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
     at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
     at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
     at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
     at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
     at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
     at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
     at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
     at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
     at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
     at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
     at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
     at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
     at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
     at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
     at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
     at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
     at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
    Caused by: java.sql.SQLDataException: data exception: string data, right truncation
     at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
     at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
     at org.hsqldb.jdbc.JDBCPreparedStatement.fetchResult(Unknown Source)
     at org.hsqldb.jdbc.JDBCPreparedStatement.execute(Unknown Source)
     at org.dbunit.database.statement.SimplePreparedStatement.addBatch(SimplePreparedStatement.java:80)
     at org.dbunit.operation.RefreshOperation$RowOperation.execute(RefreshOperation.java:192)
     at org.dbunit.operation.RefreshOperation$InsertRowOperation.execute(RefreshOperation.java:258)
     at org.dbunit.operation.RefreshOperation.execute(RefreshOperation.java:115)
     ... 30 more
    Caused by: org.hsqldb.HsqlException: data exception: string data, right truncation
     at org.hsqldb.error.Error.error(Unknown Source)
     at org.hsqldb.error.Error.error(Unknown Source)
     at org.hsqldb.types.CharacterType.castOrConvertToType(Unknown Source)
     at org.hsqldb.types.CharacterType.convertToType(Unknown Source)
     at org.hsqldb.StatementDML.getInsertData(Unknown Source)
     at org.hsqldb.StatementInsert.getResult(Unknown Source)
     at org.hsqldb.StatementDMQL.execute(Unknown Source)
     at org.hsqldb.Session.executeCompiledStatement(Unknown Source)
     at org.hsqldb.Session.execute(Unknown Source)
     ... 36 more