WildFly Undertow – How to Configure a Request Dump

If you need to debug the request headers send to Wildfly application server you can configure a Request-Dumper. There for change the standalone.xml file and add a filter-ref and filter configuration into the subsystem section of undertow. See the following example:

... 
<subsystem xmlns="urn:jboss:domain:undertow:2.0">
....
 <server name="default-server">
       ...
      <host name="default-host" alias="localhost">
          .....
          <filter-ref name="request-dumper"/>
      </host>
 </server>
....
<filters>
    .....
    <filter name="request-dumper" class-name="io.undertow.server.handlers.RequestDumpingHandler" module="io.undertow.core" />
</filters

This will print out all the request information send by a browser.

Wildfly and MVC 1.0 Ozark

I just started to build a new Java EE Web Application based on the new MVC 1.0 Framework which will become part of Java EE8. I tried to run the application on Wildfly 9.0.2.

Setup a Maven Project

To setup a MVC 1.0 Web Application with maven is tquite simple. I Just added the following dependencies into my pom.xm :

<!-- mvc-api -->
<dependency>
  <groupId>javax.mvc</groupId>
  <artifactId>javax.mvc-api</artifactId>
  <version>1.0-pr</version>
</dependency>
<dependency>
  <groupId>org.mvc-spec.ozark</groupId>
  <artifactId>ozark-resteasy</artifactId>
  <version>1.0.0-m03</version>
</dependency>

As ozark is based on jersey you need the jersey-container-servlet. As ozark is based on Java 8 it is also necessary to start Wildfly with JDK 8. Otherwise the war file can not be deployed.

The application class

Next I added an application class with a resurce mapping /api/

@ApplicationPath("api")
public class MyApplication extends Application {
}

This class is necessary to call the application URL like

/myapp/api/hello?name=xx

Here is my controller class:

@Path("hello")
public class HelloController {
 @Inject 
 private Greeting greeting; 
 private static Logger logger = Logger.getLogger(HelloController.class.getName());

 @GET
 @Controller
 @View("/pages/hello.xhtml")
 public void hello(@QueryParam("name") String name) {
 logger.info("set new message: "+name);
 greeting.setMessage("Hello "+name);
 }
}

On the first look the conroller is triggered. But currently I am not able to return the target page (in my example /pages/hello.xhtml)

The reason seems to be that the jersey servlet container will not replace the resteasy implementation for the application.

Maybe someone knows how to solve this problem?


Update 15.Aug. 2017

Finally I solved the deployment issues in Wildfly. To get Ozark running together with Wildfly first you need to add the Jersey Dependencies to your project. So the pom.xml looks like this:

 ....
<dependencies>
 <!-- JEE Dependencies -->
 <dependency>
 <groupId>javax</groupId>
   <artifactId>javaee-api</artifactId>
   <version>7.0</version>
   <scope>provided</scope>
 </dependency>
 <!-- MVC Dependencies -->
 <dependency>
   <groupId>javax.mvc</groupId>
   <artifactId>javax.mvc-api</artifactId>
   <version>1.0-edr2</version>
 </dependency>
 <dependency>
   <groupId>org.glassfish.ozark</groupId>
   <artifactId>ozark</artifactId>
   <version>1.0.0-m02</version>
 </dependency>
 <dependency>
   <groupId>org.glassfish.jersey.containers</groupId>
   <artifactId>jersey-container-servlet</artifactId>
   <version>2.23.1</version>
 </dependency>
 <dependency>
   <groupId>org.glassfish.jersey.ext.cdi</groupId>
   <artifactId>jersey-cdi1x</artifactId>
   <version>2.23.1</version>
 </dependency>
 <dependency>
 <groupId>org.glassfish.jersey.ext</groupId>
 <artifactId>jersey-bean-validation</artifactId>
 <version>2.23.1</version>
   <exclusions>
     <exclusion>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator</artifactId>
     </exclusion>
   </exclusions>
 </dependency>
  ....
 </dependencies>
....

The important part here is to deactivate the jersey hibernate-validation. This can be don with the ‘exclusion’ tag of maven.

Wildfly Deployment Descriptors

In the next step we need to provide two wildfly deployment descriptors to ensure that the RestEasy Subsystem is deactivated.

1. Deactivate Wildfly JAX-RS RestEasy Subsystem

To deactivate RestEasy add the file “jboss-deployment-structure.xml” into the WEB-INF-folder with the following content:

<?xml version="1.0" encoding="UTF-8"?> 
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2"> 
 <deployment> 
  <exclude-subsystems> 
   <subsystem name="jaxrs" /> 
  </exclude-subsystems> 
 </deployment> 
</jboss-deployment-structure>

2. Prevent implizit bean archives without beans.xml

To deactivate bean archives with a beans.xml add the file “jboss-all.xml” into the Web-INF folder with the following content:

<jboss xmlns="urn:jboss:1.0"> 
   <weld xmlns="urn:jboss:weld:1.0" require-bean-descriptor="true"/> 
</jboss>

See also: https://docs.jboss.org/author/display/WFLY8/CDI+Reference

3. Add the bean.xml file

Finally make sure that your web project contain an empty beans.xml file in the WEB-INF folder:

<?xml version="1.0"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
       version="1.1" bean-discovery-mode="all">
</beans>

 


Update 18.Sep. 2017

In the meantime the Ozark project worked on a new implementation to make the MVC implementation independend from Jersey. So now it is possible to user Ozark together with Wildfly without changing the configuration. You need to include the following dependencies:

 <dependency>
   <groupId>javax.mvc</groupId>
   <artifactId>javax.mvc-api</artifactId>
   <version>1.0-SNAPSHOT</version>
 </dependency>
 <dependency>
   <groupId>org.mvc-spec.ozark</groupId>
   <artifactId>ozark-resteasy</artifactId>
   <version>1.0.0-m03-SNAPSHOT</version>
 </dependency>

See als:

Wildfly – HeapSize

The default memory setting for Wildfly are not very high and can be to less for deployed applications. The default VM settings are typically:

  • -Xms64m
  • -Xmx512m
  • -XX:MaxPermSize=256m

For production mode this can be increased by editing the “bin/standalone.conf” file. To increase the memory size from 512MB to 2GB change the following line from:

JAVA_OPTS="-Xms64m -Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true"

into

JAVA_OPTS="-Xms2048m -Xmx2048m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true"

The settings depend on the applications deployed on wildfly.

JSF 2 and bookmarkable URLs

With JEE6 and JSF2 we finally have the great feature of bookmarkable URLs. This fixes one of the most awful faults of JSF that pages were not bookmarkable. An application can now become bookmarkable with some modifications. (See details about bookrmarkble URLs in Ryan Lubke’s Blog)

In a JSF web application you will usually have a <h:command link> or <h:commandbutton> like this:

<h:commandLink action="#{workflowController.load()}">
    <h:outputTextvalue="My action link" />
</h:commandLink>

In this example the action method returns a navigation outcome. Since JSF2 this action outcome can be also a jsf page URL (e.g /page/my_page.xhml), so no more explicit navigation rule is necessary. But the result is not bookmarkable.

To replace this with a bookmarkable URL you can replace the JSF component with the new  <h:link>. See the following example:

<h:link outcome="#{workflowController.load()}">
    <f:param name="id" value="#{workitem.item['$uniqueid']}"/>
    <h:outputText value="My action link" />
</h:link>

The trick here is, that the link is extended with a URL query param ‘id’.  Now the HTML outcome of the JSF component will look like this.

<a href="http://localhost:8080/myapp/page/my_page.xhtml?id=1">My action Link</a>

The result is simmilar to a <h:commandLink> with the difference that the URL is now set to the browsers URL. So far this new link can be bookmarked, but it is not automatically working. To resolve this new URL you have to customize your jsf page to evaluate the new query param (in this example my_page.xhml).

You can add the following metadata tag to extract the ID.

<h:head>
 <f:metadata>
 <f:viewParam name="id" value="#{workflowController.deepLinkId}" />
 </f:metadata>
</h:head>

In my example I have a method ‘getDeepLinkId’ in my workflowController Bean. The method just loads the corresponding object into my controller.

public void setDeepLinkId(String adeepLinkId) {
 this.deepLinkId = adeepLinkId;
   if (deepLinkId != null && !deepLinkId.isEmpty()) {
       // load the business object....
       this.load(deepLinkId);
       // finally destroy the deepLinkId to avoid a reload on the next
       // post event
       deepLinkId = null; // !
    }
 }

This method is necessary so in case the bookmarkable URL is requested later from a user we load the corresponding Object before we load the page.

That’s it.

h:command Buttons

The bookmarkable URLs can become a little bit tricky if you have more complex action methods. For example I used in a h:commandButton like this:

<h:commandButton action="#{workflowController.process}" value="My button">
 <f:setPropertyActionListener
    target="#{workflowController.workitem.item['$ActivityID']}"
     value="#{activity.item['numactivityid']}" />
</h:commandButton>

This is a case where replacing <h:commandButton> with <h:button> will not work out of the box. This is because the outcome property can not evaluate the action result which can – in my case – also become null. To solve this the navigation rules come back into the game. You can achieve the same result as shown in the first example with a navigation rule placed in the faces-config.xml. See the following example:

<navigation-rule>
   <navigation-case>
   <from-outcome>workitem</from-outcome>
   <to-view-id>/page/my_page.xhtml</to-view-id>
   <redirect>
     <view-param>
       <name>id</name>
       <value>#{workflowController.workitem.item['$uniqueid']}</value>
     </view-param>
   </redirect>
 </navigation-case>
</navigation-rule>

Now I moved the param ‘id’ out to the navigation rule with the identifier ‘workitem’. If my action result form the h:commandButton is ‘workitem’ the navigation rule computes the bookmarkable URL:

<a href="http://localhost:8080/myapp/page/my_page.xhtml?id=1">My action Link</a>

I hope this short examples will help you to build bookmakrable jsf applications.

Using “curl” to request the Imixs-Workflow Rest API

The command line tool ‘curl’ is useful in cases when you just want to check some REST APIs from a console. You can find a lot of information about how to use curl on curl.haxx.se.

If you want to test the Imixs Rest API you need in most cases a basic authentification against the Workflow Server. This is an example how to send username/password along with a GET request:

curl --user admin:mypassword http://localhost:8080/imixs-microservice/workflow/worklist

This examples returns the worklist for the User ‘admin’ from a Imixs-Workflow Rest Service running on localhost port 8080.

If you don’t specify the media type Imixs-Workflow will return an HTML output. You can see this also in your Browser. But Imixs-Workflow also supports the media types JSON and XML. To request the same URL in JSON you can add a Header parameter like this:

curl --user admin:mypassword -H "Accept: application/json" http://localhost:8080/imixs-microservice/workflow/worklist

or if you want to get the same response in XML format:

curl --user admin:mypassword -H "Accept: application/xml" http://localhost:8080/imixs-microservice/workflow/worklist

If you know the UniqueID of a workitem, which is included in the worklist result you can also request a single Workitem from the Imixs-Workflow. See the following curl example to request a workitem in JSON format:

curl --user admin:adminadmin -H "Accept: application/json" http://localhost:8080/imixs-microservice/workflow/workitem/14b65352f58-259f4f9b

This example returns the content of the Workitem with the UniqueID ’14b65352f58-259f4f9b’. You can also restrict the result to a subset of properties when you add the query parameter ‘items’:

curl --user admin:adminadmin -H "Accept: application/json" http://localhost:8080/imixs-microservice/workflow/workitem/14b65352f58-259f4f9b?items=txtname;$processid

See the Imixs-Workflow RestAPI for more information.

If you want to test what is possible with Imixs-Workflow REST API and curl you can try the Imixs-Microservice. Imixs-Microservice provides a full featured Workflow System based on a REST API. Imixs-Microservice also supports Docker so you do not need to install a Application Server by your self.

JSF and Transactioncontext

Today I want to talk about a detail in the JSF Framework, which is on the first view not obviously. In different to Spring, business logic placed in a JSF front-end controller (JSF Backing Beans) did not initializes a separate transaction context. Normally business logic which need to be transaction save should be spread out into EJBs. EJBs are the recommended place for business logic. So in JSF/EJB business logic should be put into stateless session EJBs and controlled the page flow of a web application through the so called front end controllers  – JSF Backing beans. As I mentioned before spring starts a transaction context also in front-end controllers, but jsf does not.

So what is the problem here? When you look at the following JSF example, you maybe will not recognize the problem at first:

//jsf bean...
@EJB ejb1;
...
public String process(businessobject) {
 ejb1.op1(businessobject);
 ejb1.op2(businessobject);
 ....
}

The JSF front-end controller method ‘process(businessobject)’ injects an EJB and calls two ejb methods. This will propaply work without any side effects. But it can produce errors in some cases. The problem in this pattern is that the front-end controller performed two apparently dependent business actions completely separately. If these two methods need to be transaction save but are operating on the same database entities this can result in serious problems. In a high concurrent system indeed this pattern can cause a corrupted DB state even if you thought JPA will solve all the transaction stuff for you.

The reason for the unexpected behavior is the missing wrapping transaction. Each ejb method starts it own transaction with all the transaction control provided by the ejb container. But the hole business method is not transaction save.

To solve this you have two possible solutions:

1) add a UserTranaction context to the front-end controller:

//jsf bean...
@Resource UserTransaction tx;
@EJB ejb1;
...
public String process(businessobject) {
 try {
   tx.begin();
   ejb1.op1(businessobject);
   ejb1.op2(businessobject);
 finaly {
   tx.commit();
 }....
}

In this example now the jsf controller starts itself the UserTransaction. As a result both EJB methods (with default transaction mode ‘mandatory’) run in the same transaction context. Even operations on the database in a high concurrent system will be transaction save.

2) Merge the EJB Methods into one transaction save business method

The second solution merges both ejb methods into a single EJB method call:

// JSF bean calls new ejb method...
public String process(Entity entity) {
 ejb1.op1op2(entity);
 // ...
}

with the following ejb implementation:

// EJB
public void op1op2(Entity entity) {
 op1(entity);
 op2(entity);
}

Now the new ejb method is transaction save an there is no need to fiddle with UserTransaction in the jsf fornt-end controller.

The second solution is recommended because there is no more risk that the transaction context is split by the front-end. And you can reuse the new ejb method easily with now need to think about the transaction context scenarios.

Maybe this will help you solving some problems with jsf transaction context in the future.

Force Git to hard checkout a branch

I run into a situation with a git repository that I was no longer able to switch between branches. Git complains about uncommitted changes. But I was sure that my local repository should not have any changes.

For force a hard checkout and pull use the following git commands. NOTE: this will overwrite any local changes – so be careful:

git checkout mybranch
git fetch --all
git reset --hard origin/mybranch
git pull