How to convert docx/odt to pdf/html with Java?

décembre 6, 2012 64 commentaires

How to convert docx/odt to pdf/html with Java? This question comes up all the time in any forum like stackoverflow. So I decided to write an article about this topic to enumerate the Java (open source) frameworks which manages that.

Here some paid product which manages docx/odt to pdf/html converters :

To be honest with you, I have not tried those solution because it’s not free. I will not speak about them in this article.

Here some open source product which manages docx/odt to pdf/html converters :

  • JODConverter : JODConverter automates conversions between office document formats using OpenOffice.org or LibreOffice. Supported formats include OpenDocument, PDF, RTF, HTML, Word, Excel, PowerPoint, and Flash. It can be used as a Java library, a command line tool, or a web application.
  • docx4j: docx4j is a Java library for creating and manipulating Microsoft Open XML (Word docx, Powerpoint pptx, and Excel xlsx) files. It is similar to Microsoft’s OpenXML SDK, but for Java. docx4j uses JAXB to create the in-memory object representation.
  • XDocReport which provides:

Here criteria that I think which are important for converters :

  • best renderer : the converter must not loose some formatting information.
  • fast : the converter must be the more fast.
  • less memory intensive to avoid OutOfMemory problem.
  • streaming: use InputStream/OutputStream instead of File. Using streaming instead of File, avoids some problems (hard disk is not used, no need to have write right on the hard disk)
  • easy to install: no need to install OpenOffice/LibreOffice, MS Word on the server to manage converter.

In this article I will introduce those 3 Java frameworks converters and I will compare it to give Pros/Cons for each framework and try to be more frankly because I’m one of XDocReport developer.

If you want to compare result of conversion, performance, etc of docx4j and XDocReport quickly, you can play with our live demo which provides a JAX-RS REST converter service.

Lire la suite…

Publicités
Catégories :XDocReport Étiquettes : , , , , ,

Eclipse RCP/RAP and Remoting with JAX-RS, Spring Data JPA and CXF DOSGi [step4]

juin 18, 2012 8 commentaires

In [step3] we have managed our UserService on Client and Server side with JAX-RS and Apache CXF DOSGi.

Embedding an HTTP server in Equinox

At this step the server side works with the HTTP Server Jetty which is an OSGi bundles. This mode is called Embedding an HTTP server in OSGi container : it means that HTTP server and WEB application are OSGi bundles. The OSGi container starts the HTTP server bundle. Embedding an HTTP server in Equinox explains how this mean is done with Equinox.

You can resume « embedding an HTTP server in OSGi container » like this :

OSGi container -> HTTP Server (bundle) -> WEB Application (bundle).

Equinox in a Servlet Container (ServletBridge)

It works great but sometimes you have not the luck to have an HTTP Server which supports OSGi like Apache Tomcat. For instance in our case, when we wished to deploy our XDocReport RAP Application on CloudBees, whish provides an Non OSGI HTTP Server Apache Tomcat.

Fortunatly, Server-Side Equinox provides Embedding OSGi container in a servlet container mode : it means that it’s a WEB Application which contains the OSGi container (and another bundles) which start the OSGi container. Equinox in a Servlet Container explains how this mean is done with Equinox.
You can resume « embedding OSGi container in a servlet container » like this :

HTTP Server -> WEB Application -> OSGi container.

To manage this mode you must create a classic WAR which hosts your OSGi plugins and ServletBridge. In this article we will explain how to create a WAR with our UserService on server side with the Eclipse Plug-In Libra WAR Product which was created for creating WAR from RAP Application launches. But it can be used too with OSGi launches (like we need in this article).

To create a WAR of CXF DOSGi application (server side), you must :

  • register your JAX-RS service with HttpService :
    <!-- HttpService -->
    <entry key="org.apache.cxf.rs.httpservice.context" value="/UserService" />
    
  • create a WAR which hosts OSGi bundles and ServletBridge. WAR Product gives you the capability to create a *.warproduct file from a launch (RAP, RCP, OSGi lanches, etc). This *.warproduct file is used to export it into a WAR to generate WAR.

At the end of this article we will create the the cxf-dosgi-jpa.war WAR. I have deployed this WAR on the CloudBees to see it on action. You can test for instance go at http://cxf-dosgi-war.opensagres.cloudbees.net/UserService/user/findAll to see JSON of the all users.

Lire la suite…

Create a WAR from RAP Application with Libra WAR Product [step3]

juin 13, 2012 2 commentaires

In [step2] we have created WAR Product files from RAP launches. In this article we will generate WAR by using the export WAR feature of the WAR Product to generates two WARs:

We will deploy generated WARs in a non OSGi HTTP Server Apache Tomcat. You can see the online demo of the rap-jpa.war created with WAR Product deployed on CloudBees which provides an Apache Tomcat at http://rap-war.opensagres.cloudbees.net/eclipsespring.

We will see in this article that projects of eclipsespring_step10.zip contains 2 problems when WAR will be exported and deployed:

  • .qualifier must not used in the Host of fragments.
  • pay attention with build.properties of Plug-in /Fragments which must include the whole files (META-INF, fragment.xml, plugin.xml, etc).

Those 2 errors are interesting because it works with RAP launch but not with WAR Product.

Lire la suite…

Catégories :Eclipse RAP, Libra, WAR Product

Create a WAR from RAP Application with Libra WAR Product [step2]

juin 13, 2012 3 commentaires

In the [step1] we have installed (My) WAR Product Plug-in. In this article we will create two WAR products from the 2 RAP launches:

  • RAP Client – JPA Dao launch starts RAP Application which displays paginated users list from Database Derby (it uses JPA implementation for Dao).
  • RAP Client – Mock Dao launch starts RAP Application which displays paginated users list from Java Map (it uses Mock implementation for Dao).

At the end of this article we will have 2 WAR Products :

In the next article [step3] we will generate two WARs from the two WAR Products created in this article by using the Export WAR action.

Lire la suite…

Catégories :Eclipse RAP, Libra, WAR Product

Create a WAR from RAP Application with Libra WAR Product [step1]

juin 12, 2012 5 commentaires

In the Eclipse RCP/RAP with Spring DM, Spring Data JPA and Remoting [step10] article we have created a RAP Application which displays list of user with pagination :

Now we wish create a classic WAR of the RAP Application to deploy the RAP Application with any HTTP Server (which doesn’t support OSGi, like Apache Tomcat). This WAR will be created by using the Libra WAR Product.

You can see the online demo of the rap-jpa.war created with WAR Product deployed on CloudBees which provides an Apache Tomcat at http://rap-war.opensagres.cloudbees.net/eclipsespring.

Lire la suite…

Catégories :Eclipse RAP, Libra, WAR Product

Eclipse RCP/RAP and Remoting with JAX-RS, Spring Data JPA and CXF DOSGi [step3]

juin 6, 2012 4 commentaires

In [step2] we have implemented the JAX-RS Client which consumes the UserService#findAll() with JAX-RS:

@Path("/user")
public interface UserService {

	@GET
	@Path("/findAll")
	@Produces(MediaType.APPLICATION_JSON)
	Collection<User> findAll();
...
}

We have seen that JAX-RS Client fails when UserService#findAll(Pageable pageable) is called, because we have not annoted this method with JAX-RS:

1031 [Thread-5] ERROR org.apache.cxf.jaxrs.client.ClientProxyImpl  - Method fr.opensagres.services.UserService.findAll is not a valid resource method
	at org.apache.cxf.jaxrs.client.ClientProxyImpl.reportInvalidResourceMethod(ClientProxyImpl.java:546)

In this article we wish to export and import with JAX-RS the UserService#findAll(Pageable pageable) which returns the paginated list of the User which uses Spring Data – Commons structures :

  • Pageable : this parameter is the pagination request.
  • Page: the findAll method returns this structure which is the result of the pagination.

On other words we will annotate the UserService#findAll(Pageable pageable) like this :

@POST
@Path("/findAllPage")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
Page<User> findAll(Pageable pageable);

However when I have managed JAX-RS with Spring Data structure, I had 2 big problems coming from :

  • Spring Data – Commons: Spring Data Page and Pageable are interfaces and not Pojo. JAX-RS works with Pojo which are annotated with JAXB annotations. How do manage Spring Data Page and Pageable interfaces with JAX-RS? Fortunately, JAXB 2.0 provides XmlJavaTypeAdapter (please read Using JAXB 2.0’s XmlJavaTypeAdapter) which gives the capability to serialize Page and Pageable interfaces with JAXB. I have suggested this idea to Oliver Gierke, the lead of the Spring Data and he is developing JAXB Adapter with SpringDataJaxb.java. However in this article we will not use this class (because this class is not finished) but we will create our own JAXB adapter which will be more simply to understand how to work the JAXB Adapter.
  • Apache CXF: on server side when CXF tries to serialize the Page class with JAXB, it fails because the JAXBContext doesn’t know the User class. This problem comes from that CXF is not able to populate the JAXBContext automaticly with Parameterized class (in our case , we have Page<T> and T=User, the JAXBContext is filled just with Page but not with User). You can fix the problem by setting extra class to the JSONProvider :
    <bean id="jsonProvider" class="org.apache.cxf.jaxrs.provider.JSONProvider">
    	<property name="singleJaxbContext" value="true" />
    	<property name="extraClass">
    		<list>
    			<value>fr.opensagres.domain.User</value>
    		</list>
    	</property>
    </bean>
    

    We will do that in this article, but I have created the patch CXF-4359 which fixes the explained problem below to avoid declaring extra classes for JSONProvider.

Lire la suite…

Catégories :Apache CXF, DOSGi, Spring Data JPA

Eclipse RCP/RAP and Remoting with JAX-RS, Spring Data JPA and CXF DOSGi [step2]

mai 31, 2012 2 commentaires

In [step1] we have downloaded CXF DOSGi « Multi Bundle Distribution » and created the fr.opensagres.remoting.exporter.dosgi.jaxrs bundle
to export on server side the UserService#findAll() with JAX-RS:

@Path("/user")
public interface UserService {

	@GET
	@Path("/findAll")
	@Produces(MediaType.APPLICATION_JSON)
	Collection<User> findAll();
...
}

In this article we will create the importer bundle fr.opensagres.remoting.importer.dosgi.jaxrs which will create a JAX-RS Client with Spring bean :

<jaxrs:client id="jaxrsUserService" address="http://127.0.0.1:9000/fr/opensagres/services/UserService"
	serviceClass="fr.opensagres.services.UserService" inheritHeaders="true">
</jaxrs:client>

and will register this JAX-RS Client in the OSGi register services as UserService :

<osgi:service ref="jaxrsUserService" interface="fr.opensagres.services.UserService" />

For recall, the Simple Client bundle fr.opensagres.simpleclient consumes a UserService in the Thread FindAllUsersThread from the OSGi registry services and display User list every 5 seconds. In our case the UserService instance will be the JAX-RS Client retrieved from the OSGi registry services :

<osgi:reference id="userService" interface="fr.opensagres.services.UserService" cardinality="0..1" timeout="1000" />

This JAX-RS Client UserService will be setted in the FindAllUsersThread with Dependency Injection :

<bean id="FindAllUsersThread" class="fr.opensagres.simpleclient.FindAllUsersThread"
		init-method="start" destroy-method="interrupt">
	<property name="userService" ref="userService"></property>
</bean>

This FindAllUsersThread (client side) consumes the UserService#findAll() every 5 seconds to display user list on the console :

// 1) findAll
users = userService.findAll();
displayUsers("findAll", users);

Lire la suite…

Catégories :Apache CXF, DOSGi