J
js
The webservice endpoint ( the server ) is not under my control,
but it expects an XML document with a specific DTD, using HTTP. No WSDL.
I have the DTD(s), and I have "compiled" them to generate
the Java classes using JAXB 2.0.
So these are all I have .... DTDs, and the generated Java classes from the DTDs.
I am able to marshall and unmarshall fine. When marshalling,
I marshall to a StringWriter and writing the contents / buffer \
of the StringWriter to the Http output stream, like so:
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty( "jaxb.formatted.output", true );
marshaller.marshal( svcInit, writer );
// Using Jakarta-HttpClient
HttpClient httpClient = new HttpClient();
PostMethod method = new PostMethod( this.URL );
method.setFollowRedirects(true);
method.addRequestHeader("Content-Type", "text/xml; charset=UTF-8");
method.setRequestBody( writer.toString() );
httpClient.executeMethod( method );
BufferedReader reader = new BufferedReader(
new InputStreamReader( method.getResponseBodyAsStream()));
StringBuffer buffer = new StringBuffer();
String line = null;
while( ( line = reader.readLine()) != null) {
buffer.append( line );
buffer.append( "\n" );
}
method.releaseConnection();
System.out.println( "Response: \n" + buffer.toString() );
JAXBContext jaxbResultContext=JAXBContext.newInstance(
"org.openmobilealliance.mlp.result");
Unmarshaller unmarshaller = jaxbResultContext.createUnmarshaller();
Object obj = unmarshaller.unmarshal(
new StreamSource( new StringReader( buffer.toString() ) ) );
SvcResult svcResult = (SvcResult) obj;
The response / returned XML is also parsed correctly,
and the correct object is returned by the unmarshaller.
Next, I want to use a Service and a Dispatch instead of using HttpClient.
What I DON'T understand are:
1) What is the "servicename" that I must pass to "Service.create() " ?
From the code below, it seems that I can actually use any name for the servicename.
2) What is the "portname" ? I can see that I can leave it null, and it works.
Here is the relevant piece of code, taken from an example that I saw on the web:
String URL = "http://localhost:9210/LocationQueryService";
URI nsURI = new URI("urn:yahoo:yn");
QName serviceName = new QName( "yahoo", nsURI.toString());
//QName portName = new QName( "yahoo_port",nsURI.toString());
Service s = Service.create( serviceName );
URI address = new URI( this.URL );
// A null portName works. What is it for then ????
//s.addPort(portName, HTTPBinding.HTTP_BINDING, address.toString());
s.addPort(null, HTTPBinding.HTTP_BINDING, address.toString());
//Dispatch<Object> d = s.createDispatch(portName, jaxbContext,
Service.Mode.MESSAGE);
Dispatch<Object> d = s.createDispatch(null, jaxbContext,
Service.Mode.MESSAGE);
Map<String, Object> requestContext = d.getRequestContext();
requestContext.put(MessageContext.HTTP_REQUEST_METHOD,
new String("POST"));
SvcResult svcResult = (SvcResult) d.invoke( svcInit );
Even though the call works, it THINKS that the XML being returned is invalid.
I say "it THINKS", because the returned XML __IS__ valid,
as it works if I use Jakarta HttpClient as shown above.
XML reader error: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[2,125]
Message: The markup declarations contained or pointed to by the document type declaration must be well-formed.
at com.sun.xml.ws.encoding.xml.XMLMessage.create(XMLMessage.java:108)
at com.sun.xml.ws.encoding.XMLHTTPCodec.decode(XMLHTTPCodec.java:143)
at com.sun.xml.ws.transport.http.client.HttpTransportPipe.process(HttpTransportPipe.java:133)
at com.sun.xml.ws.handler.HandlerPipe.process(HandlerPipe.java:107)
at com.sun.xml.ws.client.Stub.process(Stub.java:121)
at com.sun.xml.ws.client.dispatch.DispatchImpl.doInvoke(DispatchImpl.java:163)
at com.sun.xml.ws.client.dispatch.DispatchImpl.invoke(DispatchImpl.java:189)
at test.LocationRequestTestAsWebServiceClient.sendRequestAsWs(LocationRequestTestAsWebServiceClient.java:101)
at test.LocationRequestTestAsWebServiceClient.testInvalidService(LocationRequestTestAsWebServiceClient.java:156)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at test.LocationRequestTestAsWebServiceClient.main(LocationRequestTestAsWebServiceClient.java:177)
Caused by: XML reader error: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[2,125]
Message: The markup declarations contained or pointed to by the document type declaration must be well-formed.
at com.sun.xml.ws.streaming.XMLStreamReaderUtil.wrapException(XMLStreamReaderUtil.java:246)
at com.sun.xml.ws.streaming.XMLStreamReaderUtil.next(XMLStreamReaderUtil.java:70)
at com.sun.xml.ws.message.source.PayloadSourceMessage.<init>(PayloadSourceMessage.java:58)
at com.sun.xml.ws.message.source.PayloadSourceMessage.<init>(PayloadSourceMessage.java:63)
at com.sun.xml.ws.api.message.Messages.createUsingPayload(Messages.java:137)
at com.sun.xml.ws.encoding.xml.XMLMessage.create(XMLMessage.java:100)
... 24 more
Here is the returned XML:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svc_result SYSTEM "MLP_SVC_RESULT_300.DTD" [<!ENTITY % extension SYSTEM "MOBILARIS_MLP_EXTENSION.DTD"> %extension;]><svc_result ver="3.0.0">
<slia ver="3.0.0">
<pos>
<msid>46701000001</msid>
<pd>
<time utc_off="+0100">20061116054704</time>
<shape>
<CircularArcArea srsName="www.epsg.org/#4124">
<coord>
<X>72 00 09N</X>
<Y>016 00 16E</Y>
</coord>
<inRadius>0</inRadius>
<outRadius>500</outRadius>
<startAngle>0</startAngle>
<stopAngle>120</stopAngle>
</CircularArcArea>
</shape>
</pd>
</pos>
</slia>
</svc_result>
It seems to be complaining about the semi-colon character in ( %extension; )
but it expects an XML document with a specific DTD, using HTTP. No WSDL.
I have the DTD(s), and I have "compiled" them to generate
the Java classes using JAXB 2.0.
So these are all I have .... DTDs, and the generated Java classes from the DTDs.
I am able to marshall and unmarshall fine. When marshalling,
I marshall to a StringWriter and writing the contents / buffer \
of the StringWriter to the Http output stream, like so:
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty( "jaxb.formatted.output", true );
marshaller.marshal( svcInit, writer );
// Using Jakarta-HttpClient
HttpClient httpClient = new HttpClient();
PostMethod method = new PostMethod( this.URL );
method.setFollowRedirects(true);
method.addRequestHeader("Content-Type", "text/xml; charset=UTF-8");
method.setRequestBody( writer.toString() );
httpClient.executeMethod( method );
BufferedReader reader = new BufferedReader(
new InputStreamReader( method.getResponseBodyAsStream()));
StringBuffer buffer = new StringBuffer();
String line = null;
while( ( line = reader.readLine()) != null) {
buffer.append( line );
buffer.append( "\n" );
}
method.releaseConnection();
System.out.println( "Response: \n" + buffer.toString() );
JAXBContext jaxbResultContext=JAXBContext.newInstance(
"org.openmobilealliance.mlp.result");
Unmarshaller unmarshaller = jaxbResultContext.createUnmarshaller();
Object obj = unmarshaller.unmarshal(
new StreamSource( new StringReader( buffer.toString() ) ) );
SvcResult svcResult = (SvcResult) obj;
The response / returned XML is also parsed correctly,
and the correct object is returned by the unmarshaller.
Next, I want to use a Service and a Dispatch instead of using HttpClient.
What I DON'T understand are:
1) What is the "servicename" that I must pass to "Service.create() " ?
From the code below, it seems that I can actually use any name for the servicename.
2) What is the "portname" ? I can see that I can leave it null, and it works.
Here is the relevant piece of code, taken from an example that I saw on the web:
String URL = "http://localhost:9210/LocationQueryService";
URI nsURI = new URI("urn:yahoo:yn");
QName serviceName = new QName( "yahoo", nsURI.toString());
//QName portName = new QName( "yahoo_port",nsURI.toString());
Service s = Service.create( serviceName );
URI address = new URI( this.URL );
// A null portName works. What is it for then ????
//s.addPort(portName, HTTPBinding.HTTP_BINDING, address.toString());
s.addPort(null, HTTPBinding.HTTP_BINDING, address.toString());
//Dispatch<Object> d = s.createDispatch(portName, jaxbContext,
Service.Mode.MESSAGE);
Dispatch<Object> d = s.createDispatch(null, jaxbContext,
Service.Mode.MESSAGE);
Map<String, Object> requestContext = d.getRequestContext();
requestContext.put(MessageContext.HTTP_REQUEST_METHOD,
new String("POST"));
SvcResult svcResult = (SvcResult) d.invoke( svcInit );
Even though the call works, it THINKS that the XML being returned is invalid.
I say "it THINKS", because the returned XML __IS__ valid,
as it works if I use Jakarta HttpClient as shown above.
XML reader error: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[2,125]
Message: The markup declarations contained or pointed to by the document type declaration must be well-formed.
at com.sun.xml.ws.encoding.xml.XMLMessage.create(XMLMessage.java:108)
at com.sun.xml.ws.encoding.XMLHTTPCodec.decode(XMLHTTPCodec.java:143)
at com.sun.xml.ws.transport.http.client.HttpTransportPipe.process(HttpTransportPipe.java:133)
at com.sun.xml.ws.handler.HandlerPipe.process(HandlerPipe.java:107)
at com.sun.xml.ws.client.Stub.process(Stub.java:121)
at com.sun.xml.ws.client.dispatch.DispatchImpl.doInvoke(DispatchImpl.java:163)
at com.sun.xml.ws.client.dispatch.DispatchImpl.invoke(DispatchImpl.java:189)
at test.LocationRequestTestAsWebServiceClient.sendRequestAsWs(LocationRequestTestAsWebServiceClient.java:101)
at test.LocationRequestTestAsWebServiceClient.testInvalidService(LocationRequestTestAsWebServiceClient.java:156)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at test.LocationRequestTestAsWebServiceClient.main(LocationRequestTestAsWebServiceClient.java:177)
Caused by: XML reader error: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[2,125]
Message: The markup declarations contained or pointed to by the document type declaration must be well-formed.
at com.sun.xml.ws.streaming.XMLStreamReaderUtil.wrapException(XMLStreamReaderUtil.java:246)
at com.sun.xml.ws.streaming.XMLStreamReaderUtil.next(XMLStreamReaderUtil.java:70)
at com.sun.xml.ws.message.source.PayloadSourceMessage.<init>(PayloadSourceMessage.java:58)
at com.sun.xml.ws.message.source.PayloadSourceMessage.<init>(PayloadSourceMessage.java:63)
at com.sun.xml.ws.api.message.Messages.createUsingPayload(Messages.java:137)
at com.sun.xml.ws.encoding.xml.XMLMessage.create(XMLMessage.java:100)
... 24 more
Here is the returned XML:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svc_result SYSTEM "MLP_SVC_RESULT_300.DTD" [<!ENTITY % extension SYSTEM "MOBILARIS_MLP_EXTENSION.DTD"> %extension;]><svc_result ver="3.0.0">
<slia ver="3.0.0">
<pos>
<msid>46701000001</msid>
<pd>
<time utc_off="+0100">20061116054704</time>
<shape>
<CircularArcArea srsName="www.epsg.org/#4124">
<coord>
<X>72 00 09N</X>
<Y>016 00 16E</Y>
</coord>
<inRadius>0</inRadius>
<outRadius>500</outRadius>
<startAngle>0</startAngle>
<stopAngle>120</stopAngle>
</CircularArcArea>
</shape>
</pd>
</pos>
</slia>
</svc_result>
It seems to be complaining about the semi-colon character in ( %extension; )