This is about using JAX-WS with EclipseLink MOXy and my problem of not being able to use MOXy's external mapping documents in this combination. (The same actually seems to apply to JAX-RS as well, but I'm limiting the details to JAX-WS to keep this from becoming even longer than it already is).
I first describe (in some detail) the context of my requirements and the test code I've written to try and solve them. The actual question follows at the end of the post.
The context:
In some legacy parts of our project, we use JAX-WS directly on top of a simple server-side POJO model. The model is part of an API that we use for direct Java calls, but we also provide a SOAP layer implementing the same Java interface as our direct implementation, i.e. we have an IManager interface using our model, and the caller doesn't care whether his IManager instance is the local implementation or a SOAP client that calls the JAX-WS server wrapper for the local implementation.
Back when we started implementing the model, we didn't know much about JAXB, so the model has no JAXB annotations and everything is auto-deduced by JAX-WS. From the JAX-WS annotated server classes, we create a client using wsgen and wsimport. But since the model is part of our API, and the model generated by wsimport is separate set of classes (albeit with identical signatures), we have to wrap all client calls with methods that copy between these two models. Copying from one model to the other is implemented manually and has to be updated manually for every tiny change in the API model.
Since both server and client are under our control, we'd like to use the same set of (hand-written) model classes in the server and the client implementation. I've spent the past few weeks playing around with a test project that works, but doesn't completely satisfy me yet.
I built my test project in three steps:
Step 1: Implement a simple test API consisting of a model and a manger interface. Then create a simple implementation.
In my case, the model consists mainly of and IPerson and an IBook interface, and the IModelManager has methods to get, store/update and delete persons and books. The interface also provides a factory for creating new persons and books, so client projects only need the API at compile time (and the implementation at runtime).
Step 2: Provide modules for serialization to and from XML and JSON.
Because of its support of external mapping documents, I played around with EclipseLink MOXy. This allowed me to take my model from step 1 and add XML binding declarations in my separate serialization project. I could also write my serialization utility classes in such a way that the client code calling them only knows about the API, i.e. all method signatures rely only on the model interfaces and not the implementation classes. All this without touching the classes from step 1 - all the serialization stuff was cleanly layered on top of the Java implementation project.
Step 3: Provide SOAP and REST layers via JAX-WS and JAX-RS.
Now I wrote server classes for SOAP and REST, using JAX-WS and JAX-RS annotations. From the JAX-WS classes I generated a client with wsgen and wsimport and wrapped that in a client-side IModelManager implementation which simply redirects the calls to the client class generated by wsimport. For the JAX-RS classes I used Jersey with annotations in my sever class and wrote a IModelManager implementation which uses the Jersey client classes to call the REST service.
This is where I lost some of the nice functionality from step 2.
Using the JAX-WS EclipseLink plugin, all the JAX-WS code uses MOXy for serializing and deserializing the model (or at least I think it does). But I couldn't find a way to specify my external binding files. I had to add annotations to my actual model implementation from step 1 (and even to the API, because the model also includes an enum referenced from the interfaces and the enum needs JAXB annotations as well). I also had to change my JAX-WS server class to use the model implementation classes instead of the interfaces (for now I simply use casts where necessary, assuming there will never be another model implementation).
Using the WSDL and schema generated from the updated model by wsgen, I can call wsimport with a custom JAXB bindings XML to generate a client that maps all the types from the generated XSD to my existing model classes instead of generating new ones. The result is a client interface that accepts and returns the model interfaces from my API and always uses the standard implementation. I just have to write simple wrappers and cast my model implementation classes to API interfaces in several places, which is a massive improvement over our legacy code with its duplicate (and triplicate) models and loads of copying logic.
The question:
I'm not happy with having to annotate all my model classes directly (and even the enums in the API), especially considering that I had a working serialization/deserialization pipeline without annotations in step 2. Presumably, if I could provide wsimport and the code that starts up the sever-side JAX-WS implementation with my MOXy mapping documents, I could do without any annotations just like in step 2. It even seems to me that if I could provide wsgen with the mapping files, I could use my API interfaces (instead of implementation classes) in the server-side JAX-WS methods and do without all the casts, and perhaps even without the JAXB bindings file that manually maps the wsgen created XSD types to my existing classes.
But I haven't been able to find a way to provide JAX-WS with the MOXy mappings, neither the wsgen and wsimport tools nor the client or server side code. Is there something I'm missing, or if not, is this indeed a gap in JAX-WS's MOXy bridge, and is there a chance to fill it to get the full MOXy functionality in a future version? Or did I make a fundamental error in my line of thinking and there either cannot be a solution or there already is one? (Hence my detailed description of my test project)
The target platform is plain Java 8, either as a standalone application (with Jetty, using javax.xml.ws.Endpoint to publish the SOAP service and Jersey for the REST service), or Tomcat with Jersey. My tests run directly in JUnit using Endpoints and JerseyTest, plus manual tests in Tomcat.
Related
We have a big project which is composed by JEE modules, JAVA client applications, Android applications, and other self-made java projects.
Because of the variety of projects, we decided to make java libs projects and java entity projects which are common to JEE, Java client applications and Android applications in the goal of limit code redundancy between projects.
At the beginning, we only had Java Clients and Restfull web services on the JEE server side which were exchanging data using JAXB XML Binding API. So it was easy to use JAXB annotations on our Classes in the entity project (which is set as dependency on Java Client project and JEE projects). Both sides could easily encode and decode XML data with the same annotations.
Now that we have an Android app, I wanted to use the same way to exchange data. The thing is that JAXB is 'depreciated' on Android. So I found in Jackson lib that there is a JaxbAnnotation parameter for getting data which is bind with JAXB but I'm not convinced by the full compatibility of the solution.
I also tried using JSON binding since I saw that JSON-B will be the standard in JavaEE 8 but it seems that it needs JavaEE API classes and I don't think that it's good to add it to Android project.
So my question is: What is the best practice to exchange data between JEE Restfull web services and Android application using the same entity dependency (and same parsing API) and limiting the XML or JSON binding annotation on the entity objects?
I hope that you will well understand the problem.
Thank you.
Let's name your entities project entities-module. This project contains POJO classes annotated with JAXB annotations such as: #XmlElement, #XmlType, etc. Since, like you wrote, "JAXB is 'depreciated' on Android" you need to choose between: read JAXB annotations by other tools or create new customised POJO structure.
Read JAXB annotations by other tools
Jackson library has good support for JAXB annotations. All you need to do is to use jackson-module-jaxb-annotations module. It is easy to register and if you already use Jackson for serialising/deserialising JSON this is obvious choice. How to do that you can find reading answers for this question on SO: Using JAXB with Google Android.
Pros:
You do not need to create new POJOs schema.
In case of changes in Restful API you use next version of entities-module project.
Cons:
Problems with enabling JAXB on Android.
Performance issues linked with using heavy JAXB and Jackson module layers.
New module
Second choice is to create new module with POJOs and use faster and smaller library like SimpleXML.
Pros:
Better performance
No problems with building app with depreciated JAXB classes.
You can optimise structure: ignore unused fields, choose better types, etc.
Cons:
You need to create new module with new classes structure.
Learn and maintain new library
In case of changes in API you need to duplicate changes in few modules.
You need to take a look on above pros and cons list and decide what is the best for you.
I would like to also add two more options:
Replace JAXB annotations with Jackson annotations. Jackson has really good XML support beside great for JSON. It will enable for you easy support for JSON and XML formats in your API. Also, you can use Jackson library on Android.
Create new JSON API for Android app. Mostly, UI flows on Android app is different than on Web App and you will, probably, end up with that idea anyway.
When building RESTful services, I always come up against the issue of how to develop a client library that can distribute to users of the system.
To take a simple example, say there is a entity call person, and you want to support the basic CRUD functionality through your RESTFul service.
To save a person, the client needs call POST method and pass the
appropriate data structure, say in JSON.
To find people by birthday, your service will reply with a response containing a list of people objects
To delete an person, your service will respond with a success or
failure message.
From the above examples, there are already two objects that may be shared with the client: the person object and the response object. I have tried a few ways of accomplishing this:
Including the Person object from your server call in the client library. The downside to this approach are:
The client code become tightly coupled with your server code. Any
changes from server side will require client to make update during
the same release.
Person's object may contain dependencies or annotation used for
persistence or serialization. The client cares nothing about this
libraries but are forced to include them.
Include a sub class of Map which is not directly tight to Person's object but contains some helper classes to set required fields.
Looser coupling, but could result in silent errors when data structure from server changes.
Use a descriptive file like Apache Thrift, WADL or Json Schema to generate client objects during compilation time. this solve the issue of object dependencies but still creates a hard dependency. This is almost like creating a WSDL for SOAP. However, this approach is not widely used and some times difficult to find examples.
What's the best way to publish a client jar for your application, so that
Its easy for client to use
Does not create tight coupling and some tolerance for server side changes
If you answer is better documentation of the API, what's is a good tool to generate these documents from Java annotation and POJOs.
This is a common problem, regardless of the protocol used for communication.
In some of the REST APIs we've been working with recently (JAX-RS based), we create DTO objects. These are just dumb POJOs (with some additional annotations for JAXB to do some marshalling/unmarshalling for us automatically). We build these as a submodule (in maven) and provide them as a JAR so that any other projects using our API can use the DTOs if they wish. Obviously, if you want to provide your own client library, it can make use of these DTOs. Having them provided as a separate JAR (which any app can depend on) means clients aren't pulling in crazy dependencies that they don't need (your whole serverside code).
This keeps things fairly well decoupled.
On the other hand, you really don't need to provide a client. It's REST after all. Provided your REST API is well constructed and follows HATEOAS principles, your API should be easily crawlable/browsable, i.e. you shouldn't need any other descriptive scheme. If you need WADLs or other similar constructs, your API probably isn't very RESTful.
Hi : I've been using Jackson for JSON processing internally , and I want to serve these objects as Jsons to an external API (REST) (now, they are stored internally as java objects) .
The obvious implementation would be to write some kind of query engine that reads requests, retrieves objects from the underlying data store, and then serializes them into Jsons using Jackson.
However I'm starting to realize that there are APIs that already can be used to assemble such web services , taking care of a lot of the mundane details (security, query parsing, REST coordination) . For example, it appears that jersey annotations can be used to define REST services ....
So my question is : what are the state of the art in Java EE JSON based web services, and what do these services use as data stores (I.e. Plaintext? RDBMS? Object data services?)
Most importantly... what is the functional difference between the different apis for xml and json data mapping i.e. jersey/Jackson/JaxB ?
Aside from Jersey (and other JAX-RS impls like RESTeasy), which use Jackson, you might also benefit from using something like jDBI for binding relational data in POJOs first.
It does many things bigger ORMs (like Hibernate) do, but is simpler to use for most common tasks.
Or if you prefer Hibernate, use Jackson Hibernate module to handle some edge cases there may be when reading/writing POHOs as JSON.
There is a plugin for Jersey that will take your JAXB annotated objects and serialize them as JSON automatically. Jersey (JAX-RS) is a really good offering.
You can also use JPA annotations on the same objects and a JPA provider like Eclipse Link for a lot of your database needs. A basic relational database can handle most website's needs.
JAVA had released some specifications called JAX-RS to standardise the development of RESTfull web services using J2EE. These specifications are just the definitions and not the concrete implementation .
There are various implementations providers of these APIs(specifications). Jersey, RestEasy, RestLet, Apache-cxf are few such implementations which can be used to implement RESTfull services in JAVA.
Specifically to Jersey, It is not just limited to the implementation of the JAX-RS APIs. It is a framework which has its own set of APIs built by extending JAX-RS capabilities and provides additional capabilities to further ease the development of REST APIs in JAVA.
JAXB stand for Java architecture for XML binding which is another specification provided by JAVA to marshall and unmarshall Java objects to XML and vice versa. Again, Its just the specification and not the concrete implementation.
Coming to Jackson, It is just a JSON processor(typically one of the implementation of JAXB) used to marshall and unmarshall objects from Java to JSON. Jersey uses Jackson internally to convert Java objects to JSON and vice versa.
Jersey is an implementation of JAX-RS. You can think of JAX-RS as an Common interface build for RESTful Web Services. The implementation of this interface is provided by vendors. There are many implementation of this interface available like JERSEY and Rest-Easy. On the other hand Jackson is a Json Processor. It helps you in converting your objects to json and vice versa.
At work, we currently have a WSDL interface as well as a semi-RESTful interface that we're looking to expand upon and take it to the next level.
The main application runs using Servlets + JSPs as well as Spring.
The idea is that the REST and WSDL are interfaces for an API that will be designed. These (and potentially other things in future) are simply a method through which clients will be able to integrate with the interface.
I'm wondering if there are any suggestions or recommendations on frameworks / methodologies, etc for implementing that under-lying API or does it make sense simply to create some Spring beans which is called either by WSDL or REST?
Hope that makes sense.
Have a look at Eunicate it is great . You are using spring , Spring has had support of SOAP for a while and Spring 3 has support of REST (Creating and Consuming).
Your approach makes sense. Probably the most important advice is to make the external API layer as thin as possible. You can use Axis, Apache CXF, Jersey, etc. to handle the implementation of the REST or SOAP protocols, but the implementation of those services should just load the passed in data into a common request object, and pass that into a separate service that handles the request and returns a response object which the external API layer will marshall into the correct format for you.
This approach works especially well when you have a competitor providing similar services and you want to make it easy for their customers to switch. You just build a new external API that mirrors the competitors, and simply translates their format to your internal api model and provided your services are functionally equivalent, you're done.
This is a really late response, but I have a different view on this topic. The traditional way as we know it is to unmarshall xml to java and marshall java to xml. However if the wsdl changes then it would effectively be a structural change in the code which would again require a deployment.
Instead of the above approach if we list the fields mentioned in the wsdl in a presistent store, load the mappings in memory and prepare our structures based on these mappings we would have to have many less changes for this..Thus IMO instead of using existing libraries a configurable approach to unmarshalling and marshalling should be taken.
I am using netbeans 6.9. I have made a JAX-WS service that returns a complex type, I have also made a JAX-WS client to consume it.
The JAX-WS system automaticly creates a class for the client, inferred from the WSDl spec. I want to make my own class for this using JAXB annotations, so that I can add some extra functions to it.
How do I go about replacing the autogenerated file with my own one? Could I also use the same class in the service to control how it is transmitted?
Thanks!
Why replace the generated class?
From your description, it sounds like a good case for using the Decorator design pattern.
I have done this on a JAX-RPC project, and it worked very well.