It seems to me that Mule's REST Router module, which I've previously blogged about, is gaining popularity as a viable alternative to the Jersey module. Yet, the REST Router has a serious limitation in that it's unable to generate a WADL: the REST equivalent of a WSDL. Recently, I had to overcome this limitation owing to a customer requirement for producing client code from the WADL.
Consider the Mule config below:
The REST Router processes HTTP requests that have a URL path matching the templateURI pattern attribute. Non-matching requests are ignored by the router and passed on to the subsequent flow processor which in this case is a static component. Each nested block in the router corresponds to an HTTP method. A GET request is processed by the rest-router:get element, a PUT request is processed by the rest-router:put element, and so on.
WADL generation isn't a feature supported by the REST Router. If I was using the Jersey module in this example, I'd get the service WADL on hitting the URL http://localhost:8081/application.wadl. Although I'd like to avoid using Jersey for various reasons, I could leverage the library's WADL generation feature:
The above modified Mule config routes WADL requests to Jersey and all other requests to the REST Router. Upon receiving a WADL request, Jersey returns the WADL derived from the JAX-RS annotated org.ossandme.CommentResource. CommentResource describes in Java the same RESTful interface described by the REST Router. Since all service logic is performed by the REST Router, I implement the resource as a Java interface instead of a class:
This example is a Maven project hosted on GitHub. To run it, (1) open your console and enter from the project root's directory:
(2) Then deploy the package on Mule 3.3.x standalone runtime. Accessing the URL http://localhost:8081/application.wadl will give you the following:
Open Source Software And Me
A blog about my adventures in open source software
Monday, 25 March 2013
Saturday, 2 March 2013
Posting & Processing JSON with jQuery & Spring MVC
Consider an HTML form containing numerous input fields. When the user clicks on the form's submit button, the fields need to be sent as JSON to a service that under the hood is implemented in Spring MVC.
A jQuery function transforms and posts the form's inputs:
Through the $('form').submit(...) function (line 61), jQuery intercepts any click on the submit button and posts the form with the $.ajax(...) function (line 63). Before sending the data, jQuery transforms the form's inputs to JSON using JSON.stringify($(this).serializeArray()) (line 66). This function outputs a JSON string consisting of a list of key-value pairs:
On the service side, I have the controller to process the form:
getCreateClientForm() returns the HTML form to the user. The more interesting method is processSubmitCreateClient(...).
The headers annotation attribute tells Spring that processSubmitCreateClient(...) should be invoked only if the HTTP request header Content-Type is set to application/json. Furthermore, @RequestBody tells Spring to bind the JSON data to the client paramater which is a list of maps. processSubmitCreateClient(...) iterates through each element to merge the individuals maps into a single map to facilitate processing.
I add the Jackson library to the project's POM since Spring requires a JSON deserializer to perform the data binding:
You can grab the complete example from GitHub and run it from the project root directory using the following command:
From your browser, enter "http://localhost:8080/jq-springmvc-json/create-client.html" to access the form.
A jQuery function transforms and posts the form's inputs:
Through the $('form').submit(...) function (line 61), jQuery intercepts any click on the submit button and posts the form with the $.ajax(...) function (line 63). Before sending the data, jQuery transforms the form's inputs to JSON using JSON.stringify($(this).serializeArray()) (line 66). This function outputs a JSON string consisting of a list of key-value pairs:
On the service side, I have the controller to process the form:
getCreateClientForm() returns the HTML form to the user. The more interesting method is processSubmitCreateClient(...).
The headers annotation attribute tells Spring that processSubmitCreateClient(...) should be invoked only if the HTTP request header Content-Type is set to application/json. Furthermore, @RequestBody tells Spring to bind the JSON data to the client paramater which is a list of maps. processSubmitCreateClient(...) iterates through each element to merge the individuals maps into a single map to facilitate processing.
I add the Jackson library to the project's POM since Spring requires a JSON deserializer to perform the data binding:
You can grab the complete example from GitHub and run it from the project root directory using the following command:
From your browser, enter "http://localhost:8080/jq-springmvc-json/create-client.html" to access the form.
Sunday, 27 January 2013
ReplyTo in ZeroMQ using WS-Addressing
In my last post, I mentioned how one could leverage SOAP along with WS-Addressing to implement the return address pattern in ØMQ (known in the JMS world as ReplyTo and in the MSMQ world as ResponseQueue). In this post, I'll go into more detail by giving a code example using CXF's ØMQ transport.
Below is a WSDL that is similar in many respects to the WSDL of the previous post:
Like the other WSDL, this one declares that the service has an operation named sayHi. It states that ØMQ is to be used for transporting the SOAP messages (line 29). Moreover, it declares the service and consumer communication parameters: zmq:address; zmq:serviceConfig; zmq:clientConfig (lines 43-45). Unlike the other WSDL, the socket types are push for the client and pull for the service. This means that communication between the client and service is one-way and therefore the client won't receive a reply, at least not on the same channel. Remember, since we're implementing return address, the service sends its reply onto a different channel.
This is the shell command I entered for generating the SEI and proxy classes:
The -asyncMethods switch tells CXF's wsdl2java to generate, in the SEI, for each Web Service operation an asynchronous method in addition to a synchronous one. In the consumer implementation, I use the generated SEI:
doOperation() sequence of events is as follows:
The callback terminates the program as soon as it processes the reply.
I re-run wsdl2java to generate another SEI but using the following arguments:
I use the SEI generated from the above command to implement the service:
Nothing special about GreeterImpl.java except the @Addressing annotation. This annotation is required for CXF to process the request's WS-Addressing headers.
Main.java triggers the server and consumer into action:
The complete application is on GitHub. The instructions for running the demo are almost identical to the ones of the previous post. First enter the following Maven command from the project's root directory:
Then run the demo using the java command:
You should then get the following output:
Below is a WSDL that is similar in many respects to the WSDL of the previous post:
Like the other WSDL, this one declares that the service has an operation named sayHi. It states that ØMQ is to be used for transporting the SOAP messages (line 29). Moreover, it declares the service and consumer communication parameters: zmq:address; zmq:serviceConfig; zmq:clientConfig (lines 43-45). Unlike the other WSDL, the socket types are push for the client and pull for the service. This means that communication between the client and service is one-way and therefore the client won't receive a reply, at least not on the same channel. Remember, since we're implementing return address, the service sends its reply onto a different channel.
This is the shell command I entered for generating the SEI and proxy classes:
The -asyncMethods switch tells CXF's wsdl2java to generate, in the SEI, for each Web Service operation an asynchronous method in addition to a synchronous one. In the consumer implementation, I use the generated SEI:
doOperation() sequence of events is as follows:
- Publishes the endpoint that processes the service's async reply (line 10).
- Creates a client that has WS-Addressing enabled (lines 13-14).
- Adds the ReplyTo element to the request's SOAP header (lines 17-18). The element contains the callback URL that the service will read in order to know to whom it should deliver its response and how it should deliver it.
- Calls asynchronously the SEI method sayHiAsync() (line 21). If the consumer invokes the synchronous method (i.e., sayHi()) instead of the async one, the consumer would block indefinitely after sending out the request because it will wait for a reply that it will never receive.
The callback terminates the program as soon as it processes the reply.
I re-run wsdl2java to generate another SEI but using the following arguments:
I use the SEI generated from the above command to implement the service:
Nothing special about GreeterImpl.java except the @Addressing annotation. This annotation is required for CXF to process the request's WS-Addressing headers.
Main.java triggers the server and consumer into action:
The complete application is on GitHub. The instructions for running the demo are almost identical to the ones of the previous post. First enter the following Maven command from the project's root directory:
Then run the demo using the java command:
You should then get the following output:
Labels:
ReplyTo,
SOAP,
WS-Addressing,
ZeroMQ,
ØMQ
Tuesday, 15 January 2013
SOAP over ZeroMQ with Apache CXF
You're probably asking yourself one of these two questions on reading this post's title:
With the "Why?" out of the way, let's figure out the the "How?". That is, how to process SOAP messages over ØMQ. Apache CXF is an open-source Java SOAP engine that operates over transports such as JMS, UDP, and of course HTTP. During the holidays, since I had lot of free time on my hands ;-), I extended CXF to support ØMQ as an additional transport.
What follows is an example of a Web Service and a client talking with each other over the transport [1]. Consider this WSDL fragment that I wrote, and which the service and client are based on:
I use the the wsdl2java tool that comes with the Apache CXF distribution to generate SEI and proxy classes from the above WSDL. These classes help me develop the WSDL service implementation and the client.
Next, I implement the service:
The service is published using the following code:
From the consumer-side, here's the code:
I write an additional class that triggers the execution of the service and its consumer:
- Who in his right mind would use SOAP as a data format for ØMQ?
- Why the heck would I want to have SOAP on top of ØMQ as opposed to HTTP?
For the first question, consider a system requiring:
- A return address pattern such as the one offered by JMS and MSMQ.
- Guaranteed message delivery.
- Encryption and authentication of messages.
ØMQ wasn't designed to cover these requirements so it's up to the developer to come up with a solution. The developer can re-invent the wheel and build the solution from the ground up. But why do that when other folks have already taken the trouble of writing and implementing standards that address these concerns independent of the transport used? I'm speaking of WS-*. Using a SOAP engine, we can leverage WS-* standards like WS-Addressing, WS-Security, and WS-ReliableMessaging to address the above requirements and more.
Focusing on the second question, several motivations exist for using SOAP on top of ØMQ. The first that may pop into mind is the desire to reduce latency as ØMQ incurs less overhead than HTTP. For me, strong motivations include:
- Leveraging ØMQ's low-level and high-level patterns such as publish-subscribe and pipeline.
- Dispatching messages to services while they're in a disconnected state.
With the "Why?" out of the way, let's figure out the the "How?". That is, how to process SOAP messages over ØMQ. Apache CXF is an open-source Java SOAP engine that operates over transports such as JMS, UDP, and of course HTTP. During the holidays, since I had lot of free time on my hands ;-), I extended CXF to support ØMQ as an additional transport.
What follows is an example of a Web Service and a client talking with each other over the transport [1]. Consider this WSDL fragment that I wrote, and which the service and client are based on:
The contract describes a service that publishes a single operation called sayHi. sayHi accepts an empty message and returns a string. Line 29 of the WSDL informs us that the service expects sayHi to be invoked using SOAP over ØMQ. Line 43 tells us the service address whereas lines 44-45 give additional necessary details for the client and service to establish communication. Observe that I'm using socket types req and rep for the client and service respectively. This means that the communication between client and service occurs in RPC-style.
I use the the wsdl2java tool that comes with the Apache CXF distribution to generate SEI and proxy classes from the above WSDL. These classes help me develop the WSDL service implementation and the client.
The service is published using the following code:
From the consumer-side, here's the code:
I write an additional class that triggers the execution of the service and its consumer:
I use Maven from the project's root directory to build the example:
Finally, to run the app:
The output I get is:
You'll find the complete example on GitHub. This example is basic; its purpose is to get you up and running with the transport. In my next post I'll have a more real-world example where I'll show how WS-Addressing's ReplyTo element is be leveraged to implement the return address pattern in ØMQ.
Finally, to run the app:
The output I get is:
You'll find the complete example on GitHub. This example is basic; its purpose is to get you up and running with the transport. In my next post I'll have a more real-world example where I'll show how WS-Addressing's ReplyTo element is be leveraged to implement the return address pattern in ØMQ.
1: You need the Java binding for ØMQ installed on your machine to run the example.
Thursday, 20 December 2012
Demystifying Apache CXF: A RESTful Hello World App
The first post of this how-to series showed you what it takes to expose a Hello World application as a SOAP over HTTP Web Service using CXF. For this post, I'll show you how to expose the same app as a RESTful service.
In the Java world, we use JAX-RS for mapping a class to a RESTful service. Giving a RESTful interface to our Hello World app is just a matter of adding JAX-RS annotations to HelloWorldImpl:
In the class, I tell the JAX-RS provider (i.e., CXF):
As in the previous how-to, I'm going to deploy the app onto an embedded Jetty server instead of deploying it onto a standalone web container:
RuntimeDelegate.getInstance().createEndpoint(...) is a JAX-RS method that returns an unpublished endpoint. It takes in:
Back to our Server.java file, I tell the endpoint to bind the server to the URL http://localhost:9000. Then, from the endpoint, I create a org.apache.cxf.endpoint.Server object and invoke start(...) to publish the service. Note that, underneath, org.apache.cxf.endpoint.Server is a configured Jetty.
Before testing the service, I add the required CXF libraries to the Java classpath by declaring them as dependencies in project's POM :
If you compare this POM with the POM of the first how-to, you'll note that now I've swapped the JAX-WS frontend with the JAX-RS one.
All that is left is to run the server with the following Maven commands:
Once the server is up, accessing via your browser the URL http://localhost:9000/helloWorld/sayHi/Ricston should give you "Hello Ricston".
In the Java world, we use JAX-RS for mapping a class to a RESTful service. Giving a RESTful interface to our Hello World app is just a matter of adding JAX-RS annotations to HelloWorldImpl:
In the class, I tell the JAX-RS provider (i.e., CXF):
- HelloWorldImpl is a resource available on the URL relative path "/helloWorld" (@Path("/helloWorld")).
- the HTTP reply sent back to the client should have the Content-Type set to "text/hml" (@Produces).
- sayHi is to be called when the HTTP request is a GET and the relative path is "/helloWorld/sayHi/" + [variable] (@Path("sayHi/{text}")).
- to bind the URL parameter with the method argument text (@PathParam).
As in the previous how-to, I'm going to deploy the app onto an embedded Jetty server instead of deploying it onto a standalone web container:
RuntimeDelegate.getInstance().createEndpoint(...) is a JAX-RS method that returns an unpublished endpoint. It takes in:
- a class responsible for configuring and launching the web server. This class differs across JAX-RS providers. CXF expects this class to be JAXRSServerFactoryBean.
- an object that extends Application. This user-defined class must return JAX-RS annotated classes responsible for processing client requests. For us, this means returning HelloWorldImpl:
Back to our Server.java file, I tell the endpoint to bind the server to the URL http://localhost:9000. Then, from the endpoint, I create a org.apache.cxf.endpoint.Server object and invoke start(...) to publish the service. Note that, underneath, org.apache.cxf.endpoint.Server is a configured Jetty.
Before testing the service, I add the required CXF libraries to the Java classpath by declaring them as dependencies in project's POM :
If you compare this POM with the POM of the first how-to, you'll note that now I've swapped the JAX-WS frontend with the JAX-RS one.
All that is left is to run the server with the following Maven commands:
Once the server is up, accessing via your browser the URL http://localhost:9000/helloWorld/sayHi/Ricston should give you "Hello Ricston".
Wednesday, 19 December 2012
Demystifying Apache CXF: A Hello World App
"CXF scares the sh**t out of me!". This was a client's comment during our discussion on Apache CXF and I think it's a feeling shared by many. This feeling usually arises from a complaint I hear on CXF: the lack of documentation. However, I suspect that CXF's flexibility confuses numerous newbies and therefore contributes to the negative feelings towards it. The bad news is that, for some, it's hard to live without CXF. Popular open source software such as Apache Camel, Mule, and JBoss AS rely on CXF for their out-of-the-box web service support.
With the hope of increasing the understanding of Apache CXF, I've decided to publish the first of a series of how-tos. Each how-to demonstrates how to accomplish a particular task in CXF. For example, in this one I'll show how to publish a SOAP over HTTP Web Service. Throughout the how-tos, I will assume you have knowledge of basic Java and web services (e.g., SOAP, WSDL, REST). I will also assume you have knowledge of Maven. Maven is the tool I use for setting up dependencies, build and run the apps described by the how-tos. Don't worry, I'll make the apps available on GitHub :-).
Before getting our hands dirty with this how-to, I'll give a 10,000 foot view of Apache CXF for those who are new to the framework. The following is its definition taken from CXF's official website:
With the hope of increasing the understanding of Apache CXF, I've decided to publish the first of a series of how-tos. Each how-to demonstrates how to accomplish a particular task in CXF. For example, in this one I'll show how to publish a SOAP over HTTP Web Service. Throughout the how-tos, I will assume you have knowledge of basic Java and web services (e.g., SOAP, WSDL, REST). I will also assume you have knowledge of Maven. Maven is the tool I use for setting up dependencies, build and run the apps described by the how-tos. Don't worry, I'll make the apps available on GitHub :-).
Before getting our hands dirty with this how-to, I'll give a 10,000 foot view of Apache CXF for those who are new to the framework. The following is its definition taken from CXF's official website:
"Apache CXF is an open source services [Java] framework. CXF helps you build and develop services using frontend programming APIs, like JAX-WS and JAX-RS. These services can speak a variety of protocols such as SOAP, XML/HTTP, RESTful HTTP, or CORBA and work over a variety of transports such as HTTP, JMS or JBI."
In other words, with CXF, we can mix and match frontend APIs [1], protocols and transports to implement a service. For instance, we can instruct CXF to expose a Java application's interface as a WSDL and have the app talk with clients using CORBA over IIOP. But CXF is not just used to "build and develop services". We can also use CXF to build and develop service clients such as a SOAP consumer [2].
Now that we have an idea of what CXF is, let's follow the first how-to: Publish a SOAP over HTTP Web Service that takes in a string and returns "Hello" with the input string appended to it.
I have the following class:
I want the class to be exposed to the outside world as a Web Service. That is, I want to have:
With CXF, different approaches exist for doing the above. In this post, I'll cover the standard approach and leverage CXF's support for JAX-WS. In the Java world, JAX-WS is a spec for mapping a class to a SOAP Web Service. I map HelloWorldImpl by adding annotations to it:
The JAX-WS annotations in the class instruct the JAX-WS provider (i.e., CXF) to:
The next step is to launch the Web Service so I can process SOAP requests. One strategy for launching the Web Service is to deploy the app onto a web container such as Tomcat. But this requires quite a bit of setup. I'd like keep things simple for this first how-to. JAX-WS provides an easy way for launching the Web Service from within your application [4]:
Endpoint.publish(...) tells the JAX-WS provider to start an embedded web server (Jetty for CXF) on a different thread. I give the method a URL from where the Web Service will be operating on and the class to be published as a Web Service.
What happens if I try to run the app without including the CXF libraries in the Java classpath? It will actually run without a hitch, that is, the Web Service will start up. The problem is I won't be using CXF as the JAX-WS provider. If you're using the Oracle JDK, JAX-WS RI is the default JAX-WS provider since it comes bundled with the JDK. Changing from JAX-WS RI to CXF is just a matter of declaring two CXF dependencies in the POM file:
To test the Web Service, from your console, goto the project's root directory and type:
Now that we have an idea of what CXF is, let's follow the first how-to: Publish a SOAP over HTTP Web Service that takes in a string and returns "Hello" with the input string appended to it.
I have the following class:
I want the class to be exposed to the outside world as a Web Service. That is, I want to have:
- a WSDL that reflects the class interface and is accessible to clients
- SOAP requests translated into object method invocations and method results translated into SOAP replies.
With CXF, different approaches exist for doing the above. In this post, I'll cover the standard approach and leverage CXF's support for JAX-WS. In the Java world, JAX-WS is a spec for mapping a class to a SOAP Web Service. I map HelloWorldImpl by adding annotations to it:
The JAX-WS annotations in the class instruct the JAX-WS provider (i.e., CXF) to:
- Expose HelloWorldImpl as a Web Service (@WebService)
- Set the parameter name in the WSDL to "text" (@WebParam(name = "text")) [3].
The next step is to launch the Web Service so I can process SOAP requests. One strategy for launching the Web Service is to deploy the app onto a web container such as Tomcat. But this requires quite a bit of setup. I'd like keep things simple for this first how-to. JAX-WS provides an easy way for launching the Web Service from within your application [4]:
Endpoint.publish(...) tells the JAX-WS provider to start an embedded web server (Jetty for CXF) on a different thread. I give the method a URL from where the Web Service will be operating on and the class to be published as a Web Service.
What happens if I try to run the app without including the CXF libraries in the Java classpath? It will actually run without a hitch, that is, the Web Service will start up. The problem is I won't be using CXF as the JAX-WS provider. If you're using the Oracle JDK, JAX-WS RI is the default JAX-WS provider since it comes bundled with the JDK. Changing from JAX-WS RI to CXF is just a matter of declaring two CXF dependencies in the POM file:
To test the Web Service, from your console, goto the project's root directory and type:
Accessing http://localhost:9000/helloWorld?wsdl from your browser should bring up the Web Service's WSDL.
1: A frontend programming API is an API for mapping your application interface (e.g., Java interface) to a different interface (e.g., RESTful).
2: Funnily enough, this isn't mentioned in the definition.
3: @WebParam is required because a JAX-WS provider cannot deduce the parameter name from the compiled code in some situations.
4: Note that I'm not saying this is the suggested approach for a production environment. Even though it takes more time to setup, a web container offers several advantages over an embedded approach.
1: A frontend programming API is an API for mapping your application interface (e.g., Java interface) to a different interface (e.g., RESTful).
2: Funnily enough, this isn't mentioned in the definition.
3: @WebParam is required because a JAX-WS provider cannot deduce the parameter name from the compiled code in some situations.
4: Note that I'm not saying this is the suggested approach for a production environment. Even though it takes more time to setup, a web container offers several advantages over an embedded approach.
Wednesday, 14 November 2012
A Practical Solution for XML-to-Relational Mapping
A challenge in the field of integration is persisting to a relational database the contents of an XML document [1]. At first glance, this might seem like a no-brainer. Create a database table where each column maps to an element defined in the XML document's XSD. Then write an INSERT SQL statement that iterates through each element of the XML document.
But what if an XML element has attributes? What about elements containing other elements? How will we deal with elements that may occur multiple times within an element? What if element order is important? And if the XML schema is recursive? Yikes! As other people have pointed out, XML-to-relational mapping is not a trivial problem and the solution mentioned above will only work for the simplest of XSDs.
In addition to a complex XML schema, we have another issue to consider: the size of the XSD. We could be tempted to write the mappings (i.e., the SQL) for an XSD that consists of a small no. of element definitions. On the other hand, writing the mappings for a 50 KB XSD is suicidal.
What we need is a library that hides from us the intricacies of persisting XML documents. In the Java space, attempts have been made at producing an XML-to-relational mapper. For instance, Hibernate 3 has a little known experimental feature were EntityMode.DOM4J is used to persist and retrieve XML, much in the same way you would do with POJOs. Unfortunately, this feature was considered to have too many "holes" and removed from Hibernate 4.
An alternative to Hibernate 3's EntityMode.DOM4J feature is Shrex: an open source prototype mapper originating from a paper's thesis. I think Shrex has potential. With a few code changes to the prototype, I generated a database schema from a non-trivial XSD and "shredded" an XML document into relations. Having said that, I don't think Shrex is a practical solution. First off, Shrex's code base is un-maintained. To make things worse, it's devoid of community support. Therefore, taking the plunge with Shrex means that you'll be the one maintaining it. Secondly, Shrex was developed in an academic environment and, to my knowledge, never used in the wild. You'll probably have to make significant changes to the code base so that Shrex can meet your mapping requirements.
Till now, I've presented software that do the XML-relational conversion in one step. Yet, the lack of support makes these mappers impractical for a project that must meet a tight deadline. The Java EE platform provides well supported standards for:
- Binding XML documents to objects called JAXB, and
- Persisting objects into a relational store called JPA.
Leveraging JAXB and JPA, we could use objects as a go-between for persisting XML documents [2]. However, JAXB and JPA require Java classes for holding the XML data. Moreover, these classes must be annotated with mapping instructions. Writing the classes and annotations is undoable for a large or complex XSD. But generating them is doable and we can do it using an awesome XJC extension developed by Aleksei Valikov: Hyperjaxb3.
Given an XSD, Hyperjaxb3 generates POJO classes annotated with JAXB and JPA. Let me demonstrate how to use Hyperjaxb3 by walking you through a Maven project I've developed and made available on GitHub.
The following is the XSD of the XML documents I want to persist:
If you're careful, you'll note that the complex type envelopeType has an element and attribute with identical names: "from". Running Hyperjaxb3 on this schema will generate an EnvelopeType class containing two getters and setters with the same method names; illegal under the rules of Java. To prevent a name collision, I wrote a JAXB binding file:
In the binding file, aside from the name customisation, I instruct Hyperjaxb3 to generate classes:
- that follow the JPA spec, and
- have the package name org.opensourcesoftwareandme.
In the project's POM, I configure Maven to execute the Hyperjaxb3 plugin during the build:
The plugin, by default, scans "src/main/resources" for any XSDs and generates classes from them.
In addition to the plugin, I declare the dependencies for the project:
The dependencies to note are:
- hyperjaxb3-ejb-runtime: provides utility methods for (de)serialization, retrieving the persisted ID, etc...
- hibernate-entitymanager: the JPA provider which in this case is Hibernate
- derby: the database used for testing
To test the mapping, I wrote a JUnit test case:
In a few words, the test case:
- Creates a map and populates it with configuration settings that tell Hibernate the database to use for persisting the XML document and how it should be set up.
- Initialises Hibernate with the configuration settings
- Uses Hyperjaxb3's utility classes, JAXBContextUtils and JAXBElementUtils, to deserialize the XML test document mails.xml:
- Tells Hibernate to persist the object
- Retrieves the persisted object and asserts that the data content is the same as in the XML doc.
You can run Hyperjaxb3 by entering "mvn test" from your console, which will run the test as well. The generated classes are found in the target folder.
I'm very interested in seeing other alternatives for persisting XML documents to a relational database. I'd also love to know if persisting XML documents with Hyperjaxb3 would work for your project, and if not, why.
I'm very interested in seeing other alternatives for persisting XML documents to a relational database. I'd also love to know if persisting XML documents with Hyperjaxb3 would work for your project, and if not, why.
1: The wisdom of employing a relational database instead of a document store is debatable.
2: Note that this isn't a general solution for persisting XML documents.
2: Note that this isn't a general solution for persisting XML documents.
Subscribe to:
Posts (Atom)
