Wednesday, June 04, 2014

Wildfly and Resteasy are missing support for FastInfoset collection and map...

so, if you have a REST resource returning a java.util.List or a java.util.Map, like:
@Path("people")
@Produces({"application/fastinfoset"})
@Consumes({"*/*"})
public class SomeResource {
  
  @GET
  public List<SomeType> getAll() {
  ...
    
  // and / or

  @GET
  @Path("/map")
  public Map<String, SomeType> getMap() {
  ...
and you try to access it (e.g. curl -H "Accept: application/fastinfoset" http://localhost:8080/.../resources/map) you will see

Could not find MessageBodyWriter for response object of type: java.util.ArrayList of media type: application/fastinfoset

or

Could not find MessageBodyWriter for response object of type: java.util.LinkedHashMap of media type: application/fastinfoset Unfortunately Resteasy "forgot" to implement two following classes:

@Provider
@Consumes("application/*+fastinfoset")
@Produces("application/*+fastinfoset")
public class FastInfosetCollectionProvider extends org.jboss.resteasy.plugins.providers.jaxb.CollectionProvider {
  @Override
  protected boolean suppressExpandEntityExpansion() {
    return false;
  }
}
@Provider
@Consumes("application/*+fastinfoset")
@Produces("application/*+fastinfoset")
public class FastInfosetMapProvider extends org.jboss.resteasy.plugins.providers.jaxb.MapProvider {
  @Override
  protected boolean suppressExpandEntityExpansion() {
    return false;
  }
}
I already sent my pull request, but in case it is never merged, you just have to provide two classes I showed above to make it work.

Tuesday, May 27, 2014

How to convert broken FastInfoset stream into XML?

Have you ever received a broken FastInfoset (FI) stream? Or maybe, your logging infrastructure is truncating the logs so FI messages are incomplete? If you try this piece of code:
import java.io.IOException;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import com.sun.org.apache.xml.internal.serialize.OutputFormat;
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;
import com.sun.org.apache.xml.internal.serializer.Method;
import com.sun.xml.internal.fastinfoset.sax.SAXDocumentParser;

public class FiDecoder {

  public static void main(String[] args) throws IOException, SAXException {
    XMLReader saxReader = new SAXDocumentParser();
    OutputFormat format = new OutputFormat(Method.XML, null, false);
    format.setOmitXMLDeclaration(true);
    XMLSerializer handler = new XMLSerializer(System.out, format);
    saxReader.setContentHandler(handler);
    saxReader.parse(new InputSource(System.in));
  }
}
on a broken FI stream (e.g. PersonMap-broken.fi) you will see just an exception, no XML in the standard output. The problem is that the internal buffer hold by XMLSerializer has not been flushed yet and in case of error it is just dropped. It's a problem for small FI documents where buffer has no chance to be filled up before EOF or invalid FI character. Fortunately there is a simple solution. You just need to extend XMLSerializer and handle error case correctly:
import java.io.IOException;
import java.io.PrintStream;

import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import com.sun.org.apache.xml.internal.serialize.OutputFormat;
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;

public class XmlAutoFlushHandler extends XMLSerializer implements ErrorHandler {

  public XmlAutoFlushHandler(PrintStream out, OutputFormat format) {
    super(out, format);
  }
  
  @Override
  public void fatalError(SAXParseException exception) throws SAXException {
    try {
      _printer.flush();
    } catch (IOException e) {
      throw new IllegalStateException("unable to flush the stream", e);
    }
  }

  //remainder omitted
}
Finally you have to slightly modify FiDecoder class:
    XmlAutoFlushHandler handler = new XmlAutoFlushHandler(System.out, format);
    saxReader.setContentHandler(handler);
    saxReader.setErrorHandler(handler);
    try {
      saxReader.parse(new InputSource(System.in));
    } catch (IOException | SAXException e) {
      // I don't care
    }
Done! Now when you try PersonMap-broken.fi, you will see incomplete XML (which is correct) and no exception.

Monday, December 09, 2013

CXF / Spring integration using @Configuration annotation

If you develop JAX-WS services and run outside of Java EE container (that supports e.g. @WebService annotation) you probably use Apache CXF. If you want to integrate your services with CDI (again, outside of Java EE container), you probably use CXF / Spring integration - http://cxf.apache.org/docs/writing-a-service-with-spring.html

This works fine, but the problem is if you want to use exclusively annotations and you don't use XML-base Spring configuration.

There is a solution - so far my own: https://issues.apache.org/jira/browse/CXF-5448 but I opened a discussion on CXF dev mailing list to check if it could be integrated in CXF source code:  mail thread

If you have another solution, comments or feedback please use CXF dev list.

Wednesday, August 01, 2012

Lombok - cool stuff, worth trying!

A friend of mine just shared with me Project Lombok (weird name but I guessed correctly that it's something Thai ;) As I understand the goal of this project is to minimize boilerplate Java code (like getters, setters, constructors, etc.) Very good idea!

The only question that bothers me is if it's easily possible to override any behavior (e.g. setters) without the need of resigning from Lombok auto-generatin for the rest of class' elements...

Anyway - it's really worth trying!

Wednesday, March 07, 2012

Byteman - use it when Mockito can't help

Byteman is a really cool stuff with which you could simulate JVM or OS behavior hardly possible to mock using mocking library (like Mockito). Read the full exaple (really short with no fluff) here: http://theholyjava.wordpress.com/2012/02/25/cool-tools-fault-injection-into-unit-tests-with-jboss-byteman-easier-testing-of-error-handling/

Thursday, January 05, 2012

Errata to Maven2 → Maven3 migration

In the section Cobertura plugin and Maven3 of "Maven2 → Maven3 migration - real life example" article I made a mistake that resulted in reporting a bug that does not exist.


  
    package
    
      clean
      check
    
  

should be changed to:

  
    clean
    clean
    
      clean
    
  
  
    package
    package
    
      check
    
  


Both goals instrument and check must never be in the same execution because check depends on instrument and calls it itself. So, in my example goal instrument was executed twice every time and it cause a lot of problems - many of them are still magic for me e.g. compilation error saying that ...HasBeenInstrumented class cannot be identified blah, blah, blah, even though "buggy" source code was untouched and did not use this Cobertura class. Anyway MCOBERTURA-155 is a non-issue.

Thursday, December 15, 2011

Maven2 → Maven3 migration - real life example

Couple of months after JDK 7 release I decided to update my projects to build on both new JDK and Maven3 (Maven2 previously). From JDK 7 I was expecting nothing new as the codebase of our projects should be migrated step by step as soon as the Ops start supporting new application servers that could run on Java 7. More important things were expected from Maven3, namely we wanted to shorten build time, that we already optimized by 20% using Maven2 by smart initialization of our unit tests (but that's another story). In this post I will explain what I had to change to make this happen.

Monday, December 05, 2011

FW: Garbage collection in HotSpot JVM

There is an excellent new post from Alexey Ragozin on JVM Garbage Collector:
http://www.dzone.com/links/r/garbage_collection_in_hotspot_jvm.html.
He posted almost all basics you should know about different types of GCs, how to enable them in HotSpot JVM and most importantly when to enable them.

Just go there and read it!

Friday, November 25, 2011

HotSpot (64bit server) hangs on socket read (JVM 1.7 bug?) - updated


Picture (c) Clker.com
Few days ago I started working on some maven-based project (Java 1.7.0) on my new laptop (with Windows 7 64bit installed) and I noticed that very often Maven 3 was stuck downloading JARs from the internet even though my internet connection was fine. I started investigating this issue and after checking thread dump and binary dump (DMP) I think I found a bug in HotSpot for 64bit Windows.

Wednesday, November 23, 2011

GC and preformance tuning for Tomcat (from VMware)

Coming back to my previous post "Beware of your GC": just yesterday Daniel Mikusa from VMware published his post "Performance Tuning the JVM for Running Apache Tomcat" which adds some more interesting information complementing my post. You could find "Selecting a Collector" section specifically interesting e.g.:

When you specify the option to run the concurrent collector, it is important to realize that garbage collection will happen concurrently with the application. This means that garbage collection will consume some of the processor resources that would have otherwise been available to the application. On systems with a large number of processors, this is typically not a problem. However, if your system has only one or two processors then you will likely want to enable the -XX:+CMSIncrementalMode option. This option enables incremental mode for the collector, which instructs the collector to periodically yield the processor back to the application and essentially prevents the collector from running for too long.

Enjoy!