Archive

Archive for the ‘Java’ Category

Concept to handle minimal and maximal tests in a maven project

Thursday, 26. November 2009 Andreas Höhmann Leave a comment

In real world applications we have all too often external dependencies in test cases. Sometimes theses third party are not always available (i.e. remote webservices).

For continuous integration I want check a minimal set of tests but for my local development i want check a maximal set of tests. I want run my tests on command line (via maven) and in eclipse (via testng-plugin).

Here is my idea to do that …

My project super pom defines 2 profiles:

  • test-min
    1. active by default
    2. exclude testng groups (online-tests, thirdparty-tests,…)
  • test-max
    1. run a defined testng suite
    2. the suite defines a maximal set of test (all testng groups)
<profiles>
  <profile>
    <id>test-min</id>
    <activation>
      <activeByDefault>true</activeByDefault>
    </activation>
    <build>
      <plugins>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <inherited>true</inherited>
          <configuration>
            <excludedGroups>${excludedTestGroups}</excludedGroups>
          </configuration>
        </plugin>
      </plugins>
    </build>
  </profile>
  <profile>
    <id>test-max</id>
    <build>
      <plugins>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <inherited>true</inherited>
          <configuration>
            <suiteXmlFiles>
              ${basedir}/src/test/resources/Testsuite.xml
            </suiteXmlFiles>
          </configuration>
        </plugin>
      </plugins>
    </build>
  </profile>
</profiles>
<properties>
  <excludedTestGroups>online,integration,thirdparty</excludedTestGroups>
</properties>

Each subproject must define a testng src/test/resources/Testsuite.xml:

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="TestSuite for Foobar">
  <test name="Online Tests">
    <packages>
      <package name="de.foobar.*" />
    </packages>
    <groups>
      <run>
        <include name="online" />
      </run>
    </groups>
  </test>
  <test name="Integration Tests">
    <packages>
      <package name="de.foobar.*" />
    </packages>
    <groups>
      <run>
        <include name="integration" />
      </run>
    </groups>
  </test>
  <test name="Thirdparty Tests">
    <packages>
      <package name="de.foobar.*" />
    </packages>
    <groups>
      <run>
        <include name="thirdparty" />
      </run>
    </groups>
  </test>
  <!-- Each project can define MORE groups: i.e. "interactive" -->
  <test name="Other Tests">
    <packages>
      <package name="de.foobar.*" />
    </packages>
    <groups>
      <run>
        <exclude name="online" />
        <exclude name="integration" />
        <exclude name="thirdparty" />
        <!-- Each project can define MORE groups: i.e. "interactive" -->
      </run>
    </groups>
  </test>
</suite>

If the sub project defines more exclude groups (i.e. a additional “interactive” group) then the pom must overwrite the excludedTestGroups property:

<properties>
  <excludedTestGroups>online,integration,thirdparty,interactive</excludedTestGroups>
</properties>

To check the correct configuration of the two profiles we can use help:effective-pom:

mvn -Ptest-min help:effective-pom | less

<plugin>
  <artifactId>maven-surefire-plugin</artifactId>
  <configuration>
    <excludedGroups>online,integration,thirdparty,interactive</excludedGroups>
  </configuration>
</plugin>

mvn -Ptest-max help:effective-pom | less

<plugin>
  <artifactId>maven-surefire-plugin</artifactId>
  <configuration>
    <suiteXmlFiles>
      <suiteXmlFile>d:\foobar\src/test/resources/Testsuite.xml</suiteXmlFile>
    </suiteXmlFiles>
  </configuration>
</plugin>

Now I can run min/max tests for each project which depend on the above super-pom. The test-min is the default profile and would be used on the continuous integration system (i.e. TeamCity).

Try it :)

Categories: Maven Tags: , , , ,

Maven https repository with self-signed ssl certificate

Tuesday, 17. November 2009 Andreas Höhmann 1 comment

For a private project I try to use nexus behind apache and ssl. I used a self-signed certificate.

But each nexus repository request ends with a security exception:

[WARNING] repository metadata for: 'artifact org.apache.maven.plugins:maven-enforcer-plugin' could not be retrieved from repository: nexus-plugin-releases due to an error: Error transferring file: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

I found many site for that problem and they describe always the same solution

import the self signed cert in your local truststore!

… here are the steps:

  1. download the certificate
  2. create a local truststore and import the certificat
  3. call maven with the correct security properties

The import is simple  (java keytool):

keytool.exe -importcert
            -alias nexus-xxx
            -keystore xxx.jks
            -storepass secret
            -file xxx.crt

For maven I’m using a cygwin bash alias:

alias mvn_xxx='/cygdrive/d/maven-2.2.1/bin/mvn
-gs "d:/maven-2.2.1/conf/settings-xxx.xml"
-s "d:/maven-2.2.1/conf/settings-xxx.xml"
-Djavax.net.ssl.trustStore=d:/maven-2.2.1/conf/xxx.jks
-Djavax.net.ssl.trustStorePassword=secret'

I point the global config  (-gs) and the personal config (-s) to the same file to ignore other configuration from my default maven config file (i.e. common mirros settings / repositories etc.).

And at least here is my complete maven setting-nexus settings:

<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/settings/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">

  <localRepository>D:\maven-repository-xxx</localRepository>

  <mirrors>
    <mirror>
      <id>xxx-nexus-snapshots</id>
      <mirrorOf>nexus-snapshots</mirrorOf>
      <url>https://nexus.xxx.com/content/groups/public-snapshots/</url>
    </mirror>
    <mirror>
      <id>xxx-nexus-snapshots</id>
      <mirrorOf>nexus-plugin-snapshots</mirrorOf>
      <url>https://nexus.xxx.com/content/groups/public-snapshots/</url>
    </mirror>
    <mirror>
      <id>xxx-nexus-releases</id>
      <mirrorOf>nexus-releases</mirrorOf>
      <url>https://nexus.xxx.com/content/groups/public/</url>
    </mirror>
    <mirror>
      <id>xxx-nexus-releases</id>
      <mirrorOf>nexus-plugin-releases</mirrorOf>
      <url>https://nexus.xxx.com/content/groups/public/</url>
    </mirror>
    <mirror>
      <id>xxx-nexus-releases</id>
      <mirrorOf>*</mirrorOf>
      <url>https://nexus.xxx.com/content/groups/public/</url>
    </mirror>
  </mirrors>

  <profiles>
    <profile>
      <id>xxx-nexus-mirror</id>
      <activation>
        <activeByDefault>true</activeByDefault>
      </activation>
      <repositories>
        <repository>
          <id>nexus-releases</id>
          <url>http://foobar</url>
          <releases>
            <enabled>true</enabled>
          </releases>
          <snapshots>
            <enabled>false</enabled>
          </snapshots>
        </repository>
        <repository>
          <id>nexus-snapshots</id>
          <url>http://foobar</url>
          <releases>
            <enabled>false</enabled>
          </releases>
          <snapshots>
            <enabled>true</enabled>
          </snapshots>
        </repository>
      </repositories>
      <pluginRepositories>
        <pluginRepository>
          <id>nexus-plugin-releases</id>
          <url>http://foobar</url>
          <releases>
            <enabled>true</enabled>
          </releases>
          <snapshots>
            <enabled>false</enabled>
          </snapshots>
        </pluginRepository>
        <pluginRepository>
          <id>nexus-plugin-snapshots</id>
          <url>http://foobar</url>
          <releases>
            <enabled>false</enabled>
          </releases>
          <snapshots>
            <enabled>true</enabled>
          </snapshots>
        </pluginRepository>
      </pluginRepositories>
    </profile>
  </profiles>

  <servers>
    <server>
      <id>xxx-nexus-releases</id>
      <username>foo</username>
      <password>bar</password>
    </server>
    <server>
      <id>xxx-nexus-snapshots</id>
      <username>foo</username>
      <password>bar</password>
    </server>
  </servers>

</settings>

You can replace xxx with your personal domain-alias.

Categories: Maven Tags: , , , , , , ,

Richfaces modal panel default formular action

Monday, 16. November 2009 Andreas Höhmann Leave a comment

Each input dialog should have a default action for good useability.

If the user hit ‘Enter’ then the default action should execute.

Here is my example of a richfaces modal edit dialog for such a requirement …

The dialog have input fields and 3 actions:

  • save – is the default action if the user hit ‘Enter‘ anywhere in the formular
  • cancel – is the default action if the user hit ‘Esc‘ anywhere in the formular
  • reset
<rich:modalPanel id="edit_dialog">

   <a4j:form id="edit_form" ajaxSubmit="true">

     <h:outputLabel value="What's your title:" for="title"/>
     <h:inputText  id="title" value="#{bean.title}"/>
     <h:outputLabel value="What's your name:" for="name"/>
     <h:inputText  id="name" value="#{bean.name}"/>

       ...

     <a4j:commandButton id="save"
          value="Save"
          action="#{save}"
          type="submit"
          oncomplete="if(#{facesContext.maximumSeverity==null})Richfaces.hideModalPanel('edit_dialog')"/>

     <a4j:commandButton id="reset"
          value="Reset"
          action="#{bean.reset}"
          limitToList="true"
          reRender="edit_form"
          ajaxSingle="true"
          type="reset"/>

     <a4j:commandButton id="cancel"
          value="Cancel"
          action="#{bean.cancel}"
          ajaxSingle="true"
          oncomplete="Richfaces.hideModalPanel('edit_dialog')"/>

     <rich:hotKey key="return"
         selector="#edit_form"
         handler="${rich:element('edit_form:save')}.click();event.stopPropagation();event.preventDefault(); return false;"
         disableInInput="false"/>

      <rich:hotKey key="esc"
         selector="#edit_form"
         handler="${rich:element('edit_form:cancel')}.click();event.stopPropagation();event.preventDefault(); return false;"
         disableInInput="false"/>

   </a4j:form>

</rich:modalPanel>

It’s important to define ajaxSubmit=”true” for the form! This avoid “none ajax submit of html formulars”. I will explain this in a later blog :)

With rich:hotKey I bind 2 key events to the edit formular:

  • on ‘enter’ – the handler click the save button
  • on ‘esc’ – the handler click the cancel button

Try it :D

Categories: Richfaces, jQuery Tags: , , , ,

Richfaces modal panel autofocus first input element

Monday, 16. November 2009 Andreas Höhmann Leave a comment

With jQuery it’s easy to focus the first visible input element (textfield, textarea or selectbox) for a rich:modalPanel:

<rich:modalPanel onshow="autofocus('dialog_content')">
  <h:panelGrid id="dialog_content" columns="1" width="100%" cellpadding="0" cellspacing="0">
     <a4j:form ajaxSubmit="true">
       <h:outputLabel value="What's your name:" for="name"/>
       <h:inputText  id="name" value="#{bean.name}"/>
       ...
       <a4j:commandButton id="save" value="Save my name" action="save"/>
     </a4j:form>
  </h:panelGrid>
</rich:modalPanel>
function autofocus(containerId) {
  var element = jQuery(":input:not(:button):visible:enabled:first", '#'+containerId);
  if (element != null) {
    element.focus().select();
  }
}
Categories: Richfaces, jQuery Tags: , , , , ,

Build eclipse applications with maven 3

Friday, 13. November 2009 Andreas Höhmann Leave a comment

The  tool chain for building eclipse based applications with maven becomes better and better.

Read here.

I know 2 projects using maven to build eclipse plugins:

Which project are there else?

Categories: Eclipse, Maven Tags: , , , ,

Disable backspace key in a Richfaces application

Friday, 6. November 2009 Andreas Höhmann Leave a comment

If you want disable the Backspace key in your JSF Richfaces application put this in your view:

<rich:hotKey key="backspace" handler="return false;" disableInInput="true"/>

This will register a jQuery Hotkey handler for the document. The handler is not reqistered for input elements because in input fields you need the backspace ;-) . Tested for FF3 and IE6.

Then I found out that the following snippet doesn’t work:

<rich:hotKey key="backspace"
             disableInInput="true"
             handler="alert('Backspace is disabled'); return false;" />

The Browser open the alert box and go to the previous page (in background?!). But there is a fix for that:

<rich:hotKey key="backspace"
             disableInInput="true"
             handler="alert('Backspace is disabled'); event.stopPropagation(); event.preventDefault(); return false;" />

The event variable is available in the handler function (see org.richfaces.renderkit.html.HotKeyRenderer method doEncodeEnd).

Toggle jrebel with a cygwin bash function and maven

Monday, 2. November 2009 Andreas Höhmann 1 comment

I’m using java rebel for web development with maven.

Sometimes I would run jetty with jrebel sometimes without.

For that I’m using two simple bash functions:

# ~/.bashrc

#
# Maven options
#
export INTERNAL_MAVEN_OPTS="-Xmx512m -XX:PermSize=128m -XX:MaxPermSize=128m"

#
# Java Rebel
#
export JAVA_REBEL="-Drebel.spring_plugin=true -Drebel.log=false -noverify -javaagent:D:\tools\javarebel\jrebel.jar -Drebel.packages=de.ahoehma"

function jrebel_on() {
 export MAVEN_OPTS="$INTERNAL_MAVEN_OPTS $JAVA_REBEL"
}

function jrebel_off() {
 export MAVEN_OPTS="$INTERNAL_MAVEN_OPTS"
}

Now its very simple to enable

$ jrebel_on

or disable jrebel

$ jrebel_off
Categories: Java Tags: , , , , , ,

Quality Center Mylyn Integration

Wednesday, 28. October 2009 Andreas Höhmann Leave a comment

There is a interesting project at sourceforge called qcMylyn.  The projects aims to provide a Mylyn connector for Quality Center. Support Eclipse 3.4.2, 3.5, Mylyn 3.0.5+.

I tried the released version 0.2.4 but it didn’t work because at work we are using an older version of QualityCenter (9.1). But this was no big problem I have the sourcecode (OS rocks) and I’m a programmer ;)

I found out that a other project called QcTools4J contains the java code for manipulation a QC system. They using a com4j bridge to bind QC’s otaclient.dll.

If you have trouble with a older/newer version of QC you have to update the qctools4j.

You find a short tutorial how to update qctools4j here. (read this first) … then you will come to the point where you want create a new otaclient.jar from you local otaclient.dll. Here is my simple solution for that.

I create my own otaclient maven project with the following pom:

<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>otaclient</groupId>
      <artifactId>otaclient</artifactId>
      <version>9.1.0.4372</version>
      <dependencies>
        <dependency>
          <groupId>org.jvnet.com4j</groupId>
          <artifactId>com4j</artifactId>
          <version>20080107</version>
        </dependency>
      </dependencies>
      <build>
        <plugins>
          <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
              <source>1.5</source>
              <target>1.5</target>
            </configuration>
          </plugin>
          <plugin>
            <groupId>org.jvnet.com4j</groupId>
            <artifactId>maven-com4j-plugin</artifactId>
            <executions>
              <execution>
                <id>gen-java-bridge</id>
                <goals>
                  <goal>gen</goal>
                </goals>
                <configuration>
                  <file>src/qc/OTAClient.dll</file>
                  <package>com.mercury.qualitycenter.otaclient</package>
                </configuration>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    </project>

I using the maven-com4j-plugin to generate the java layer for otaclient.

All you have to do is to extract your “qc client package” (could be download from every qc server page) into src/qc and start mvn clean package.

Then target will contain a otaclient-9.1.0.4372.jar. Copy this jar into qctools4j/lib/com.mercury.qualitycenter.otaclient-9.2.jar and rebuild qctools4j. That’s all :)

qcmylyn_otaclient

Then copy the qctools4j.jar into org.tszadel.qctools and rebuild the whole eclipse feature.

qcmylyn_qctools4j

Try it :)

My favourite java ide is eclipse

Monday, 21. September 2009 Andreas Höhmann Leave a comment
Categories: Java

Customized Richfaces Tree

Thursday, 10. September 2009 Andreas Höhmann Leave a comment

Yesterday I had to customize the Richfaces tree component, because my client wants a special layout. My solution is a little bit strange. I share it here for someone which is in the same situation ;) Here is the story …

Per default the rich:tree looks like a standard tree browser (i.e. explorer, eclipse, whatever):

rich_tree_standard

But I want this look:

rich_tree_customized

You see that the expand/collapse icon (rich_tree_expand) is on the same level with the node-icon (rich_tree_leaf). That’s very hard to fix this with CSS (it’s possible but i prefer my strange solution ;) ). The Richfaces documentation describes which parts of a tree could be customize.

We have:

  • rich-tree-node-handle and rich-tree-node-handleicon – a td which contains a link and a image to expand/collapse the node (only possible for a node not a leaf)
  • rich-tree-node-icon – is a td which contains the image for a node (a node with children)
  • rich-tree-node-icon-leaf – is a td which contains the image for a leaf (a node without children)

I decide to move the expand/collapse icon from the handle-td to the icon-td and “simulate” the user-click with Javascript:

rich_tree_expand_move

Listing 1 tree.xhtml:

<rich:tree id="tree"
              binding="#{treeBean.tree}"
              var="item"
              switchType="ajax"
              ajaxSubmitSelection="true"
              toggleOnClick="false"
              showConnectingLines="false"
              disableKeyboardNavigation="true">

    <f:facet name="iconCollapsed">
       <!-- no image for collapsed -->
       <rich:spacer width="0"  height="0" style="border: none;"/>
    </f:facet>
    <f:facet name="iconExpanded">
       <!-- no image for expanded -->
       <rich:spacer width="0"  height="0" style="border: none;"/>
    </f:facet>

    <f:facet name="icon">
       <!--  use normal node icon to toggle expand/collapse -->
       <h:panelGroup>
          <h:graphicImage value="#{item.isLeaf ? '/images/leaf.gif' : '/images/collapsed.gif'}"
                                 onclick="myToggleTreeNode(this);"
                                 rendered="#{!treeBean.isExpanded}"/>
          <h:graphicImage value="#{item.isLeaf ? '/images/leaf.gif' : '/images/expanded.gif'}"
                                 onclick="myToggleTreeNode(this);"
                                 rendered="#{treeBean.isExpanded}"/>
       </h:panelGroup>
    </f:facet>

    <f:facet name="iconLeaf">
       <h:graphicImage value="/images/leaf.gif"/>
    </f:facet>

    <rich:recursiveTreeNodesAdaptor roots="#{treeBean.roots}" var="item" nodes="#{item.children}">
       <rich:treeNode>
          <h:outputText value="#{item.name}"/>
       </rich:treeNode>
    </rich:recursiveTreeNodesAdaptor>
</rich:tree>

Listing 2 tree.js:

function myToggleTreeNode(element) {
  var elem = jQuery(element);
  // img -> span -> td
  var parent = elem.parent().parent();
  var elementId = parent.attr("id");
  // i.e. j_id31:tree:j__id39:18::j_id40:icon -> the td arround the icon-image
  var index = elementId.lastIndexOf(":icon");
  var treeNodeId = elementId.substring(0, index);
  // i.e. j_id31:tree:j__id39:18::j_id40:handle -> the td arround the original expand/collapse-image
  var handleId = treeNodeId+':handle';
  // pure jQuery not working here
  var expandElement = jQuery($(handleId));
  expandElement.trigger("click");
}

Listing 3 tree.css:

.rich-tree-node-handleicon {
  display: none;
}
Categories: JSF, Richfaces Tags: , , , ,