My service is consuming a soap service. The target service could add new fields which shouldnt break our service as long as we receive all the fields we need.
I am using CXF to generate java code from WSDL and it breaks whenever it finds a new field. Is it possible to configure CXF to ignore new fields?
The error is something like
org.apache.cxf.interceptor.Fault: Unmarshalling Error: unexpected element (uri:"http://www.a.com/sed/b/products/2014/03/types", local:"BidOnly"). Expected elements are <{http://www.a.com/sed/b/products/2014/03/types}SaleTeam>,
at org.apache.cxf.jaxb.JAXBEncoderDecoder.unmarshall(JAXBEncoderDecoder.java:905) ~[cxf-rt-databinding-jaxb-3.2.0.jar:3.2.0]
at org.apache.cxf.jaxb.JAXBEncoderDecoder.unmarshall(JAXBEncoderDecoder.java:711) ~[cxf-rt-databinding-jaxb-3.2.0.jar:3.2.0]
at org.apache.cxf.jaxb.io.DataReaderImpl.read(DataReaderImpl.java:172) ~[cxf-rt-databinding-jaxb-3.2.0.jar:3.2.0]
I tried to solve the same problem and stumbled upon this question:
CXF - webservice endpoint has changed, WSDL has not
Apparently if you set "set-jaxb-validation-event-handler" to "false" it disables this validation for the unmarshaler. So in my code I added this:
import org.apache.cxf.jaxws.EndpointImpl;
...
EndpointImpl endpoint = new EndpointImpl(...);
endpoint.getProperties().put("set-jaxb-validation-event-handler", "false");
I know I'm answering an old question, but perhaps it will be useful to someone.
Have hosted soap service using camel-cxf component with default POJO data format. Want to do schema validation and instead fault need to return custom soap message.
There are many places and many techniques to do that. It depends on your requirements and design solution.
You can do it by custom code in one of inbound CXF interceptors before request reaches first processor after Camel from endpoint.
You can do it by using Camel Validate component (maybe start looking from here: Apache Camel: Validation Component
Some time ago, after playing with different approaches I ended up with custom Processor to do validation (due to my requirements - must be inside Route, must provide all errors/warnings at once(not first only), must create custom error response with details about all errors, get better as possible performance and so on...
I used standard javax.xml.validation package.
That option is not too hard, but more coding required.
Code must create instance of javax.xml.validation.Schema out of XSD file.
It is thread safe and it can be cached.
Then out of it javax.xml.validation.Validator can be created and used.
It is not thread safe, so new one must be created every time. (It is not costly operation anyway).
Then to collect all errors and warnings at once instead of getting validation exception from first error/warrning custom Error Handler implementing org.xml.sax.ErrorHandler interface need to be provided to validator in that case. There you can collect all exception and warnings from validation and deal with them after full validation completed.
With CXF POJO format - body in Camel Message actually is not a SOAP Message body, but it
is org.apache.cxf.message.MessageContentsList; where SOAP Message body POJO is element 0, and if message has more parts they are there too.
To use javax.xml.validation.Validator Body POJO must be marshalled to javax.xml.transform.Source
MyPojoClass bodyObject = ((MessageContentsList) exchange.getIn().getBody()).get(0);
SchemaFactory schemaFactory = SchemaFactory
.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema requestedSchema = schemaFactory.newSchema(schemaUrl);
Validator validator = requestedSchema.newValidator();
// custom handler to collect all errors and warnings
SchemaValidationErrorHandler errHandler = new SchemaValidationErrorHandler();
validator.setErrorHandler(errHandler);
//Custom method convertPojo - uses JAXB Marshaller in standard way
Source xmlSource = convertPojo(bodyObject);
validator.validate(xmlSource);
After all if Error Handler collects warnings and errors and does not throw Exception right away, all errors/warnings will be in it and can be handled as needed.
P.S. Performance is better when Schema object created ones and cached somewhere. Schema object creation is costly operation.
I have to contact a Web Service (WS). I'm using JDK 1.6, maven 3.04, Spring 3.20 and apache's CXF 2.7.2. Using maven I created stubs for the WS by feeding it the wsdl file. I have a spring config for the WS client and it looks something like
servlet-context.xml
<jaxws:client id="paymentClient" serviceClass="com.xxx.payment.Payment"
address="http://127.0.0:8088/mockPaymentBinding" <!-- SOAPUI mock -->
username="username"
password="secret" />
<!- username and password are for wsdl basic authentication -->
In the Java code it looks something like
#Autowired
com.xxx.payment.Payment client;
..
// Set all needed parameters.
PaymentGetBalanceResponse response = null;
PaymentGetBalance getBalance = new PaymentGetBalance();
RequestGetBalance value = new RequestGetBalance();
value.setTransactionId("transActionId");
getBalance.setRequest(value );
// Now call the WS and get the response
response = client.getBalance(getBalance); // generated by the cxf -client argument.
The "response" line is generated as an example by CXF. Then Eclipse tells me something is missing (getbalance) and optionally creates it for me above the line. Then something else is (value) missing and so on. In the end all parameters are correctly filled in. All the missing stuff/variables/objects are in the generated stubs code.
This works like a charm BUT the address is atm hardcoded in the spring config. The configuarion parameters for the application are stored in a simple database. The contents is accesible using a spring bean so I can get at the variables in the end in the code using something like config.getValue(URL);
I hoped to being able to change the 'address' (url WS) in the code above but haven't found a way to do that. Can't find setters in the generated stub code. An alternative would be to use variables in the spring servlet-context.xml file BUT those variables have to come from the database. Second alternative. I probably/hopefully get away with starting at the bottom and using the Objectfactorys (in the stubs) to create objects. Then setting the correct parameter (either in the 'new' or a setter) and then work my way to the top. A colleguee has done this (not for 'address') and this seems to work but the code is suboptimal/'messy' at best. ALSO I would like to able to have the username and password configurable, NOT static. Did quite a bit of RTM at the CXF sites but to no avail.
Read something about JaxWsProxyFactoryBean but can't figure out how to apply it here as I use Springs #autowire functionality.
I've been breaking my brains about this issue but it seems my neurons are running in circles. ANY help/pointers is really appreciated.
From CXF User Guide: How to override the service address?.
If I've inferred the spring config correctly, I think this will do:
#Autowired
com.xxx.payment.Payment client;
// ...
BindingProvider provider = (BindingProvider)client.getServicePort();
// You can set the address per request here
provider.getRequestContext().put(
BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
"http://my/new/url/to/the/service");
I am trying to implement a RESTful service endpoint which produces XML responses. The return entity for this service call is a HashMap which has the data for the output to be generated. But I keep getting the following exception while invoking the service:
HttpMediaTypeNotAcceptableException: Could not find acceptable
representation
To investigate the issue, I wrote another endpoint which produces a response for a single object (say, Employee). I have annotated this class with #XmlRootElement and invoking it works just fine. If I remove the #XmlRootElement annotation from the Employee class, this endpoint will also fail and give the same exception which I mentioned above.
As per my understanding the root object in the ResponseEntity should be annotated with #XmlRootElement. My problem centers around how to use this annotation on collections like Map, List etc..
All help appreciated, thanks.
I don't think this is possible -- you will most likely have to create some sort of wrapper or DTO around your Collection/Map. This: Using JAXB to unmarshal/marshal a List<String> I believe is related to your use-case.
Goal
Java client for Yahoo's HotJobs Resumé Search REST API.
Background
I'm used to writing web-service clients for SOAP APIs, where wsimport generates proxy stubs and you're off and running. But this is a REST API, which is new to me.
Details
REST API
No WADL
No formal XML schema (XSD or DTD files). There are example XML request/response pairs.
No example code provided
Progress
I looked at question Rest clients for Java?, but the automated solutions there assume you are providing both the server and the client, with JAXB invoked on POJOs to generate a schema and a REST API.
Using Jersey (a JAX-RS implementation), I have been able to make a manual HTTP request:
import com.sun.jersey.api.client.*;
...
ClientConfig clientConfig = new DefaultClientConfig();
Client client = Client.create(clientConfig);
WebResource webResource = client.resource("https://hj.yahooapis.com/v1/HJAuthTokens");
webResource.accept("application/xml");
// body is a hard-coded string, with replacements for the variable bits
String response = webResource.post(String.class, body);
// parse response into a org.w3c.dom.Document
// interface with Document via XPATH, or write my own POJO mappings
The response can look like:
<?xml version="1.0" encoding="utf-8"?>
<Response>
<ResponseCode>0</ResponseCode>
<ResponseMessage>Login successful</ResponseMessage>
<Token>NTlEMTdFNjk3Qjg4NUJBNDA3MkJFOTI3NzJEMTdDNDU7bG9jYWxob3N0LmVnbGJwLmNvcnAueWFob28uY29tO0pVNWpzRGRhN3VhSS4yQVRqRi4wWE5jTWl0RHVVYzQyX3luYWd1TjIxaGx6U0lhTXN3LS07NjY2MzM1OzIzNDY3NTsxMjA5MDE2OTE5OzZCM1RBMVNudHdLbl9VdFFKMFEydWctLQ==</Token>
</Response>
Or, it can look like:
<?xml version="1.0" encoding="utf-8"?>
<yahoo:error xmlns:yahoo="http://www.yahooapis.com/v1/base.rng" xml:lang="en-US">
<yahoo:description>description</yahoo:description>
<yahoo:detail>
<ErrorCode>errorCode</ErrorCode>
</yahoo:detail>
</yahoo:error>
Questions
Is there a way to auto-generate POJOs which can be marshalled/unmarshalled without a formal schema?
Should I attempt to generate those POJOs by hand, with JAXB annotations?
Is there some tool I should be leveraging so I don't have to do all this manually?
It's interesting that they provide an HTTP URL as the namespace URI for the schema, but don't actually save their schema there. That could be an oversight on their part, which an email or discussion-list posting could correct.
One approach is to create your own schema, but this seems like a lot of work for little return. Given how simple the messages are, I wonder if you even need a POJO to wrap them? Why not just have a handler that extracts the data you need using XPath?
Edit: blast from the past, but I saw the comment, reread the question, and realized that the first sentence was hard to understand. So, clarification:
One very good habit, if you're going to write a publicly accessible web service, is to make your schema document available at the same URL that you use for the schema's namespace URI -- or better, have that URL be a link to complete documentation (the W3C XSD namespace is itself a good example: http://www.w3.org/2001/XMLSchema).
I would suggest writing beans by hand, and only annotating with JAXB annotations if you have to. For most accessors/mutators (getters/setters) you do not have to; by default all public bean accessors and fields are considered, name is derived using bean convention, and default is to use elements instead of attributes (so attributes need to be annotated).
Alternatively you can of course write schema by hand, generate beans using JAXB, if you like W3C Schema a lot. And just use resulting code, not schema, for data binding.
As to POJO: that can be very simple. Something like:
#XmlRootElement("Response")
class Response {
public int responseCode;
public String responseMessage;
public String token; // or perhaps byte[] works for automated base64?
}
and similarly for other ones. Or, use getters/setters if you like them and don't mind bit more verbosity. These are just data containers, no need to get too fancy.
And if you must auto-detect type from content, consider using Stax parser to see what the root element, and then bind using JAXB Unmarshaller, handing XMLStreamReader that points to that root element. That way you can pass different object type to bind to.
And finally: sending/receiving requests: plain old HttpURLConnection works ok for GET and POST requests (construct using, say, URL.openConnection()). Jakarta HttpClient has more features if need be. So oftentimes you don't really need a separate REST client -- they may come in handy, but generally build on simple http client pieces.
I find HTTP4E very useful for making REST calls. It is an awesome Eclipse plugin, it has tabs, syntax coloring, auto suggest, code generation, REST HTTP call replay, etc.. It does a great job of HTTP debugging, HTTP tampering, hacking. I am having so much fun with it.
http://www.ywebb.com/
Try JdkRequest from jcabi-http (I'm a developer). This is how it works:
String body = new JdkRequest("http://www.google.com")
.header("User-Agent", "it's me")
.fetch()
.body()
Check this blog post for more details: http://www.yegor256.com/2014/04/11/jcabi-http-intro.html