I'm trying to pull data from a webservice using JAX-WS and code generated by wsimport. I'm able to send the request and get a response from the server, but JAX-WS is throwing an exception when it tries to read the response because no elements in the response body have a declared namespace.
Exception in thread "main" com.sun.xml.internal.ws.streaming.XMLStreamReaderException: unexpected XML tag. expected: {http://www.theserver.com/cmdb_rel_ci}getRecordsResponse but found: {null}getRecordsResponse
WSDL Excerpt:
<wsdl:definitions xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:tns="http://www.theserver.com/cmdb_rel_ci" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sncns="http://www.theserver.com" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" targetNamespace="http://www.theserver.com">
<wsdl:types>
<xsd:schema elementFormDefault="unqualified" targetNamespace="http://www.theserver.com/cmdb_rel_ci">
<xsd:element name="getRecords">
<xsd:complexType>
<xsd:sequence>
<!-- Request arguments -->
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="getRecordsResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element maxOccurs="unbounded" minOccurs="0" name="getRecordsResult">
<xsd:complexType>
<xsd:sequence>
<!-- Response Fields -->
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>
<wsdl:message name="getRecordsSoapIn">
<wsdl:part name="cmdb_rel_ci" element="tns:getRecords"></wsdl:part>
</wsdl:message>
<wsdl:message name="getRecordsSoapOut">
<wsdl:part name="cmdb_rel_ci" element="tns:getRecordsResponse"></wsdl:part>
</wsdl:message>
</wsdl:definitions>
Successful Request and Response in SoapUI:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns2="http://www.theserver.com/cmdb_rel_ci">
<soapenv:Header/>
<soapenv:Body>
<ns2:getRecords>
<arg1>value</arg1>
<!-- Remaining Arguments -->
</ns2:getRecords>
</soapenv:Body>
</soapenv:Envelope>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<getRecordsResponse>
<getRecordsResult>
<resultField1>value</resultField1>
<resultField2>value2</resultField2>
<!-- etc. -->
</getRecordsResult>
<!-- Other getRecordsResult elements -->
</getRecordsResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
How do I tell JAX-WS that the <getRecordsResponse> element won't have a namespace? I've tried setting targetNamespace = "" in the #ResponseWrapper annotation for getRecords(), but that just makes it expect the targetNamespace parameter from #WebService instead. And when I tried as a last-ditch effort to set the WebService's target namespace blank, it tried to infer a namespace from the Java package name (e.g. "http://my_package.com").
I was unable to find a way to tell JAX-WS not to expect a namespace, but I was able to work around it by pre-processing the response in a SOAPHandler and manually adding a namespace to the XML element (by giving it a new QName that included a namespace declaration).
MyHandler.java:
public class MyHandler implements SOAPHandler<SOAPMessageContext> {
#Override
public void close(MessageContext context) {
}
#Override
public boolean handleMessage(SOAPMessageContext context) {
//Don't intercept outbound messages (SOAP Requests)
if ((Boolean)context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY)) {return true;}
SOAPMessage message = context.getMessage();
try {
SOAPBody body = message.getSOAPBody();
Iterator<SOAPElement> bodyIterator = body.getChildElements();
SOAPElement responseElement = bodyIterator.next();
responseElement.setElementQName(new QName("http://www.theserver.com/cmdb_rel_ci", origGetRecordsResponse.getLocalName(), "cmdb"));
} catch (Exception e) {e.printStackTrace();}
return true;
}
#Override
public boolean handleFault(SOAPMessageContext context) {
return false;
}
#Override
public Set<QName> getHeaders() {
return Collections.emptySet();
}
}
Then I just had to add my Handler to the HandlerChain with the following code in my main class, and it worked.
Binding binding = ((BindingProvider)port).getBinding();
List<Handler> handlers = binding.getHandlerChain();
handlers.add(new MyHandler());
binding.setHandlerChain(handlers);
The question here is
How do I tell JAX-WS that the element won't have a namespace? I've tried setting targetNamespace = "" in the #ResponseWrapper annotation for getRecords(), but that just makes it expect the targetNamespace parameter from #WebService instead.
Answer is here
https://docs.oracle.com/cd/E13222_01/wls/docs92/webserv/annotations.html
TO make sure that targetNamespace is not ignored, change the SOAPBinding style to SOAPBinding.Style.Document
Information from the above url which gives more insights into the issue.
The XML namespace of the return value. This value is used only used for document-style Web Services, in which the return value maps to an XML element.
The default value is the targetNamespace of the Web Service.
Related
I am trying to unMarshall XML data from a file with the following Schema file, using NetBeans 8.2, in a java Web Application.
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://xml.netbeans.org/schema/xSchema"
xmlns:tns="http://xml.netbeans.org/schema/xSchema"
elementFormDefault="qualified">
<xsd::complexType name="xItem">
<xsd:sequence>
<xsd:element name="item1" type="xsd:string"/>
<xsd:element name="item2" type="xsd:string"/>
<xsd:element name="item3" type="xsd:int"/>
<xsd:element name="x-price">
<xsd:complexType>
<xsd:sequence>
<xsd:element name = "item4" type="xsd:string"/>
<xsd:element name = item5" type = "xsd:float"/>
<xsd:element name = "item6" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:element name = "xList">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="x_details" type="tns:xItem" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
I created an XML Document using NetBeans and populated that with data, matching the Schema file.
The XML schema is bound to the Java Web Application using Jaxb. I have created the unmarshalling code using the jaxbu method, which looks like this
xList currentx = new xList();
//UnMarshal data from XML to Object
try {
javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(currentx.getClass().getPackage().getName());
javax.xml.bind.Unmarshaller unmarshaller = jaxbCtx.createUnmarshaller();
currentx = (xList) unmarshaller.unmarshal(fileHandle); //NOI18N
} catch (javax.xml.bind.JAXBException ex) {
// XXXTODO Handle exception
java.util.logging.Logger.getLogger("global").log(java.util.logging.Level.SEVERE, null, ex); //NOI18N
}
The resulting ArrayList currentx, contains all the instances of item1, item2 and item 3. It does not however appear to contain items 4 and 5. 'fileHandle' is a FILE object, and is obviously pointing to the correct file.
The generated files include classes for xItem and a nested static class for x-price, but whenever I try to retrieve data from the nested class, I get a null pointer exception for items4, 5 and 6, but can read items 1,2 and 3. The unmarshalling function appears to perform without any exceptions being created.
Am I using the right methods for unmarshalling all the data or am I missing something to deal with the x-price ( items 4, 5 and 6)? How is that done ?
XLM first data record and header:
<ns1:xList
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns:ns1='http://xml.netbeans.org/schema/xSchema'
xsi:schemaLocation='http://xml.netbeans.org/schema/xSchema xSchema1.xsd'>
<ns1:x_details>
<ns1:item1>AA</ns1:item1>
<ns1:item2>AA</ns1:item2>
<ns1:aitem3>212</ns1:item4>
<ns1:x-price>
<ns1:item4>GBP</ns1:item4>
<ns1:item5>75.26</ns1:item5>
<ns1:item6>04/12/2018</ns1:item6>
</ns1:x-price>
</ns1:x_details>
In your example Schema your schema seems to be invalid:
<xsd:element name = item5" type = "xsd:float"/>
and should be
<xsd:element name = "item5" type = "xsd:float"/>
also it is hard to help if your real data is missing (your XML). Could you add a full XML example?
I've been attempting to get a Spring Boot Application to generate the following SOAP Request:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:api="http://simpro4.wirelesslogic.com/api/">
<soapenv:Header/>
<soapenv:Body>
<api:getAvailableCustomerSolutions>
<GetAvailableCustomerSolutionsRequest>
<accountNumbers>
<item>xxx</item>
</accountNumbers>
</GetAvailableCustomerSolutionsRequest>
</api:getAvailableCustomerSolutions>
</soapenv:Body>
</soapenv:Envelope>
And instead when using the following code:
public class WirelessLogicClient extends WebServiceGatewaySupport {
private String endpoint = "http://simprosb.wirelesslogic.com/sandbox.php/api/customerV3";
public GetAvailableCustomerSolutionsResponse getAvailableCustomerSolutionsRequest(){
GetAvailableCustomerSolutionsRequest request = new GetAvailableCustomerSolutionsRequest();
// request params
ArrayOfString accountNumbers = new ArrayOfString();
accountNumbers.getItems().add("xxx");
// build request
request.setAccountNumbers(accountNumbers);
// send request
return (GetAvailableCustomerSolutionsResponse) getWebServiceTemplate().marshalSendAndReceive(endpoint, request, new SoapActionCallback("http://simprosb.wirelesslogic.com/sandbox.php/api/customerV3/"));
}
However when the object is marshalled, using wireshark to see the actual XML sent over the wire from the spring application, I end up with the following:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<api:GetAvailableCustomerSolutionsRequest xmlns:api="http://simpro4.wirelesslogic.com/api/">
<accountNumbers>
<item>786708</item>
</accountNumbers>
</api:GetAvailableCustomerSolutionsRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
The SOAP endpoint is rather fussy, and requires 2 changes to make this work, the namespace xmlns:api="http://simpro4.wirelesslogic.com/api/" HAS to be in the element, it will not parse a response without it. Secondly, the body contents need to be wrapped in an <api:getAvailableCustomerSolutions>, which I thought that it would have been able to resolve.
I've used a chrome plugin (Boomerang) to test the endpoint without Java, and it generates sensible requests, but I've had no end of trouble trying to get this working in Java.
I don't have to use Jax-ws, I'm open to using anything that has a maven repo; I don't want to use handlers, as this is simply one SOAP operation of many I'd have to do this for, but I'm having the same issue across all the methods I've tried thus far.
The following are the relevant bits from the WSDL:
<message name="getAvailableCustomerSolutionsRequest">
<part name="getAvailableCustomerSolutionsRequest" type="tns:GetAvailableCustomerSolutionsRequest"/>
</message>
<message name="getAvailableCustomerSolutionsResponse">
<part name="return" type="tns:GetAvailableCustomerSolutionsResponse"/>
</message>
.....
<operation name="getAvailableCustomerSolutions">
<input message="tns:getAvailableCustomerSolutionsRequest"/>
<output message="tns:getAvailableCustomerSolutionsResponse"/>
</operation>
.....
<xsd:complexType name="GetAvailableCustomerSolutionsRequest">
<xsd:all>
<xsd:element name="accountNumbers" type="tns:ArrayOfString" nillable="true"/>
</xsd:all>
</xsd:complexType>
.....
<xsd:complexType name="ArrayOfString">
<xsd:sequence>
<xsd:element name="item" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
Pom.xml
<!-- tag::wsdl[] -->
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.12.3</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<schemaLanguage>WSDL</schemaLanguage>
<schemaDirectory>src/main/resources/schemas</schemaDirectory>
<schemaIncludes>
<includes>wirelesslogicsandbox.xml</includes>
</schemaIncludes>-->
<generatePackage>wirelesslogic.wsdl</generatePackage>
</configuration>
</plugin>
I'm having a problem generating java source code based on XSD file.
Please notice that the XSD file was generated based on XML example.
XML Example
<resposta_importacao>
<RetornoEnvio xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<num_apolice xmlns="compuletra">202476600001</num_apolice>
<cod_retorno xmlns="compuletra">651</cod_retorno>
<mensagem xmlns="compuletra">Erro de layout de dadosobrigatórios: cod_cobertura</mensagem>
<id_validacao xmlns="compuletra">0</id_validacao>
</RetornoEnvio>
<RetornoEnvio xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<num_apolice xmlns="compuletra">202476600002</num_apolice>
<cod_retorno xmlns="compuletra">651</cod_retorno>
<mensagem xmlns="compuletra">Erro de layout de dados obrigatórios: cod_cobertura</mensagem>
<id_validacao xmlns="compuletra">0</id_validacao>
</RetornoEnvio>
</resposta_importacao>
Generated XSD
<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:complexType name="RetornoEnvio">
<xsd:sequence>
<xsd:element name="num_apolice" type="xsd:integer" xmlns="compuletra" />
<xsd:element name="cod_retorno" type="xsd:int" xmlns="compuletra" />
<xsd:element name="mensagem" type="xsd:string" xmlns="compuletra" />
<xsd:element name="id_validacao" type="xsd:int" xmlns="compuletra" />
</xsd:sequence>
</xsd:complexType>
<xsd:element name="resposta_importacao">
<xsd:complexType>
<xsd:sequence>
<xsd:element maxOccurs="unbounded" type="RetornoEnvio" name="RetornoEnvio" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Generated Java Class
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "RetornoEnvio", propOrder = {
"numApolice",
"codRetorno",
"mensagem",
"idValidacao"
})
public class RetornoEnvio {
#XmlElement(name = "num_apolice", required = true)
protected BigInteger numApolice;
#XmlElement(name = "cod_retorno")
protected int codRetorno;
#XmlElement(required = true)
protected String mensagem;
#XmlElement(name = "id_validacao")
protected int idValidacao;
The problem here is that the XML has the
xmlns="compuletra"
But the java class don't.
I know I can just insert the namespace attribute to the XmlElement annotation but it would be nicer if the code generation could insert it for me.
Thank you
The xmlns attribute in the element defintion in the XML Schema has nothing to do with the namespace qualification of the element. This is why JAXB isn't doing anything with it.
<xsd:element name="cod_retorno" type="xsd:int" xmlns="compuletra" />
Well, just to answer mine own question, so that it does not go unanswered..
I could achieve this namespace difference with the most obvious solution, after thinking of it a little more. Basically using two XSD files with two different namespaces and importing them in a third XSD file.
It all worked as expected.
Thank you,
Thiago
I auto-generated a solution from a WSDL file for a project I'm working on, but for some reason the solution does not seem to correctly handle the input specified by the WSDL. Does anyone know what I can do to fix it?
Given the following operation:
<wsdl:operation name="createBin">
<wsdl:input message="impl:createBinRequest" name="createBinRequest"/>
<wsdl:output message="impl:createBinResponse" name="createBinResponse"/>
</wsdl:operation>
<wsdl:message name="createBinRequest">
<wsdl:part element="impl:createBin" name="parameters"/>
</wsdl:message>
<element name="createBin">
<complexType>
<sequence>
<element name="request" type="impl:Bin"/>
</sequence>
</complexType>
</element>
<complexType name="Bin">
<sequence>
<element name="FulfillerID" type="xsd:positiveInteger"/>
<element name="BinID" nillable="true" type="xsd:positiveInteger"/>
<element name="ExternalLocationID" type="xsd:string"/>
<element name="BinType" type="xsd:string"/>
<element name="BinStatus" type="xsd:string"/>
<element name="Name" nillable="true" type="xsd:string"/>
</sequence>
</complexType>
Implemented with this code (auto-generated by eclipse):
public PositiveInteger createBin(Bin request) throws RemoteException {
throw new UnsupportedOperationException();
}
When sending this message:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:q0="http://my.api.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<q0:createBin>
<q0:request>
<q0:FulfillerID>1234</q0:FulfillerID>
<q0:BinID>1234</q0:BinID>
<q0:ExternalLocationID>1234</q0:ExternalLocationID>
<q0:BinType>Good</q0:BinType>
<q0:BinStatus>Bad</q0:BinStatus>
<q0:Name>Ugly</q0:Name>
</q0:request>
</q0:createBin>
</soapenv:Body>
</soapenv:Envelope>
I get the following error:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<soapenv:Fault>
<faultcode>soapenv:Server.userException</faultcode>
<faultstring>org.xml.sax.SAXException: Invalid element in com.api.my.Bin - request</faultstring>
<detail>
<ns1:hostname xmlns:ns1="http://xml.apache.org/axis/">localhost</ns1:hostname>
</detail>
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>
I'm 100% sure that the SOAP message is the correct format, so my server must be choking on something. When I remove the parameter, everything works swimmingly for some reason.
I can however, get the expected behavior by removing the element like so:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:q0="http://my.api.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<q0:createBin>
<q0:FulfillerID>1234</q0:FulfillerID>
<q0:BinID>1234</q0:BinID>
<q0:ExternalLocationID>1234</q0:ExternalLocationID>
<q0:BinType>Good</q0:BinType>
<q0:BinStatus>Bad</q0:BinStatus>
<q0:Name>Ugly</q0:Name>
</q0:createBin>
</soapenv:Body>
</soapenv:Envelope>
I'm searching my brain to remember where I saw this before, but I'm certain I've seen some seemingly 'invalid SOAP requests' which turned out to be invalid because the response was invalid.
In this light: could you change the generated createBin(Bin request) code to return a PositiveInteger rather than -3? Maybe if we can make te response valid, your server will stop complaining.
Good Luck!
It turns out the SAX parser is not interpreting the request that it looks like it should. Even though the parameter to the method is request, it ignores that and expects to parse an element that has a request field of type com.api.my.Bin. The problem was fixed by changing .
public PositiveInteger createBin(Bin request) throws RemoteException {
throw new UnsupportedOperationException();
}
With
public PositiveInteger createBin(CreateBin request) throws RemoteException {
throw new UnsupportedOperationException();
}
Where
public class CreateBin {
public Bin request;
/* ... */
}
Though, to be transparent, I did have to do a lot of tweaking to the CoreServiceSoapBindingStub and CoreServiceSoapBindingSkeleton that eclipse generated in order to get the whole thing not to blow up because of invalid something-or-other.
I'm trying to process some XML files using the JAXB implementation shipped in Java 7. I'm using these versions :
501 ~ % xjc -version
xjc 2.2.4
502 ~ %java -version
java version "1.7.0_01"
Java(TM) SE Runtime Environment (build 1.7.0_01-b08)
Java HotSpot(TM) Server VM (build 21.1-b02, mixed mode)
The problematic decalaration in the XML schema is the following :
<xsd:complexType name="CategorizeType">
<xsd:complexContent>
<xsd:extension base="se:FunctionType">
<xsd:sequence>
<xsd:element ref="se:LookupValue"/>
<xsd:element ref="se:Value"/>
<xsd:sequence minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="se:Threshold"/>
<xsd:element ref="se:Value"/>
</xsd:sequence>
<xsd:element ref="se:Extension" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="thresholdBelongsTo"
type="se:ThresholdBelongsToType" use="optional"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
As you can see, there are two explicit occurences of se:Value in the Type. However, it doesn't stop the compilation using xjc. And if I have a look in the Java class generated for this type, I can see that it is theoritically possible to retrieve the elements of
<xsd:sequence minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="se:Threshold"/>
<xsd:element ref="se:Value"/>
</xsd:sequence>
using the following method :
public List<Object> getThresholdAndValue() {
if (thresholdAndValue == null) {
thresholdAndValue = new ArrayList<Object>();
}
return this.thresholdAndValue;
}
Unfortunately, if I try to get the elements of the list, i can only retrieve the elements registered as threshold in my xml file, where the CategorizeType instance is defined as follow :
<Categorize thresholdsBelongTo="succeeding" fallbackValue="0">
<LookupValue>
<ns3:ValueReference>OUI_EEE92</ns3:ValueReference>
</LookupValue>
<Value>0.3</Value>
<Threshold>30.0</Threshold>
<Value>0.4</Value>
<Threshold>40.0</Threshold>
<Value>0.45</Value>
<Threshold>45.0</Threshold>
<Value>0.5</Value>
<Threshold>50.0</Threshold>
<Value>0.55</Value>
<Threshold>55.0</Threshold>
<Value>0.6</Value>
<Threshold>60.0</Threshold>
<Value>0.7</Value>
<Threshold>70.0</Threshold>
<Value>0.8</Value>
<Extension>
<ExtensionParameter name="method">MANUAL</ExtensionParameter>
</Extension>
</Categorize>
When retrieving the list, I can only see the Threshold values.
Do I make something wrong ? Is it an inner limitation of Jaxb ?
Note that I can't change the XML schema...
EDIT :
I've just run xjc with the -v option, and I obtain globally the same output. With verbosity :
xjc -verbose se/2.0/All.xsd
parsing a schema...
[WARNING] java.net.SocketException: Unexpected end of file from server
line 23 of file:/home/alexis/crap/SE-Schema-2.0/ows/2.0/ows19115subset.xsd
[WARNING] java.net.SocketException: Unexpected end of file from server
line 22 of file:/home/alexis/crap/SE-Schema-2.0/filter/2.0/filterCapabilities.xsd
compiling a schema...
[INFO] generating codee
unknown location
Without it :
xjc se/2.0/All.xsd
parsing a schema...
[WARNING] java.net.SocketException: Unexpected end of file from server
line 23 of file:/home/alexis/crap/SE-Schema-2.0/ows/2.0/ows19115subset.xsd
[WARNING] java.net.SocketException: Unexpected end of file from server
line 22 of file:/home/alexis/crap/SE-Schema-2.0/ows/2.0/owsExceptionReport.xsd
compiling a schema...
The following output just contains the name and location of the generated files.
I have forgotten to say that this xsd couldn't be compiled with the xjc shipped with Java 6. Last tried has been made with JAXB 2.1.10.I can't reproduce this behaviour now, as I'm now working with Java 7.
EDIT2 :
I've just tried to customize the binginds, as suggested in comments. My binding file is the following :
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jxb:bindings jxb:version="1.0"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
<jxb:bindings schemaLocation="schema.xsd"
node="//xsd:complexType[#name='CategorizeType']">
<jxb:bindings
node="xsd:complexContent/xsd:extension/xsd:sequence/xsd:element[#ref='se:Value'][position()=1]">
<jxb:property name="FirstValue"/>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
The first value instance is indeed replaced by a firstValue attribute in the Java code
#XmlElement(name = "Value", required = true)
protected ParameterValueType firstValue;
#XmlElements({
#XmlElement(name = "Threshold", type = LiteralType.class),
#XmlElement(name = "Value", type = ParameterValueType.class)
})
protected List<Object> thresholdAndValue;
public ParameterValueType getFirstValue() {
return firstValue;
}
public void setFirstValue(ParameterValueType value) {
this.firstValue = value;
}
public List<Object> getThresholdAndValue() {
if (thresholdAndValue == null) {
thresholdAndValue = new ArrayList<Object>();
}
return this.thresholdAndValue;
}
Unfortunately, I still obtain the same result - I still can't see my values in the list returned by getThresholdAndValues(). I'm still exploring the customization way...
Update: Sorry I had to give up on this, I just couldn't get it to work either (it would be so much easier if you could change your schema!). I was using the Codehaus JAXB maven plugin. I'm pretty sure it's a conflict caused by the two Value elements, which I tried to fix with an xjb customisation:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jxb:bindings jxb:version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<jxb:bindings schemaLocation="../xsd/example.xsd" node="/xsd:schema">
<jxb:schemaBindings>
<jxb:package name="com.example" />
<jxb:nameXmlTransform>
<jxb:elementName suffix="Element"/>
</jxb:nameXmlTransform>
</jxb:schemaBindings>
</jxb:bindings>
</jxb:bindings>
It had absolutely no effect. I tried <jxb:typeName suffix="Element"/>, and it renamed all of the JAXB classes, so I assume there's a bug with the jxb:elementName feature.
Original Post:
I've been looking at this and I'm able to replicate your problem.
I took a few liberties with your schema to simplify things, but it still contains the essential elements. Here is what I've been using:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:se="http://com.example/example"
targetNamespace="http://com.example/example"
elementFormDefault="qualified">
<xsd:element name="Categorize" type="se:CategorizeType" />
<xsd:complexType name="FunctionType">
</xsd:complexType>
<xsd:simpleType name="Value">
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
<xsd:simpleType name="Threshold">
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
<xsd:complexType name="CategorizeType">
<xsd:complexContent>
<xsd:extension base="se:FunctionType">
<xsd:sequence>
<xsd:element name="Value" type="se:Value" />
<xsd:sequence minOccurs="0" maxOccurs="unbounded">
<xsd:element name="Threshold" type="se:Threshold" />
<xsd:element name="Value" type="se:Value" />
</xsd:sequence>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:schema>
I've removed any elements/attributes not related to the issue, used name/type instead of ref, and defined the types missing from your provided schema.
My generated JAXB CategorizeType class looks like:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "CategorizeType", propOrder = {
"value",
"thresholdAndValue"
})
public class CategorizeType
extends FunctionType
{
#XmlElement(name = "Value", required = true)
protected String value;
#XmlElementRefs({
#XmlElementRef(name = "Value",
namespace = "http://com.example/example", type = JAXBElement.class),
#XmlElementRef(name = "Threshold",
namespace = "http://com.example/example", type = JAXBElement.class)
})
protected List<JAXBElement<String>> thresholdAndValue;
...
}
When I unmarshall your XML, my Categorize.Value is 0.8 (instead of the expected 0.3), and the values of each ThresholdAndValue (all Strings in my case) are 30.0, 40.0, 45.0, etc. The 0.4, 0.45, etc are missing.
When I remove the first Value element from the schema and then unmarshall, I get all of the expected values, so there's definitely a conflict!
However, when I marshall using the following JAXB setup:
ObjectFactory factory = new ObjectFactory();
CategorizeType catType = factory.createCategorizeType();
catType.setValue("0.3");
JAXBElement<String> thresh = factory.createCategorizeTypeThreshold("30.0");
JAXBElement<String> threshVal = factory.createCategorizeTypeValue("0.4");
JAXBElement<String> thresh2 = factory.createCategorizeTypeThreshold("40.0");
JAXBElement<String> threshVal2 = factory.createCategorizeTypeValue("0.45");
catType.getThresholdAndValue().add(thresh);
catType.getThresholdAndValue().add(threshVal);
catType.getThresholdAndValue().add(thresh2);
catType.getThresholdAndValue().add(threshVal2);
JAXBElement<CategorizeType> element = factory.createCategorize(catType);
// marshall to XML here!
I get the expected output:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Categorize xmlns="http://com.example/example">
<Value>0.3</Value>
<Threshold>30.0</Threshold>
<Value>0.4</Value>
<Threshold>40.0</Threshold>
<Value>0.45</Value>
</Categorize>
I'll keep looking into this!
i think you need a complexType element around
<xsd:sequence minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="se:Threshold"/>
<xsd:element ref="se:Value"/>
</xsd:sequence>
Can you insert an XSLT transformation to add a ComplexType to the schema definition before running xjc?