0

I am trying to develop an endpoint which should accept xml data and produce pdf with it. I have created the xsd file which I am using to generate JAXB Classes and I declared the xs type of request to be string like this:

<xs:element name="producepdf-request">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="xmlData" type="xs:string" />
            </xs:sequence>
        </xs:complexType>
</xs:element>

but when I pass the xml data to this endpoint as String then there is a lot of invald xml characters which are causing IOException. I create the required xml data to call this endpoint like this:

File xmlDocument = new File("C:\\Users\\stu\\Desktop\\fileName.xml");
String xmlData = FileUtils.readFileToString(xmlDocument, "UTF-8");

and clear invalid characters:

String xml10pattern = "[^"
                    + "\u0009\r\n"
                    + "\u0020-\uD7FF"
                    + "\uE000-\uFFFD"
                    + "\ud800\udc00-\udbff\udfff"
                    + "]";
xmlData  = xmlData.replaceAll(xml10pattern, "");

then pass it to the endpoint. The problem is that I still get exceptions due to invalid characters. So what is the better way of solving this issue? Is there a type to declare the request type on xsd level so that I don't have to worry about invalid characters, or is there a better way to read the xml file from the file system? Thanks.

sticky_elbows
  • 1,344
  • 1
  • 16
  • 30
  • Very probably your endpoint/servlet/webservice [does not read](https://stackoverflow.com/questions/6876697/how-to-set-request-encoding-in-tomcat) the uploaded request body with UTF-8 encoding. Maybe it would be good to see how to send you the file (client code) and what tries to read it (if it is a servlet). – m4gic Aug 30 '18 at 12:25
  • Thanks @m4gic. my endpoint is a soap web service and the client is a controller. I am sure the data I am sending is being read which is why I am getting the exception no? – sticky_elbows Aug 30 '18 at 12:32
  • Nice. What do you mean on controller? How do you assemble your request? – m4gic Aug 30 '18 at 12:37
  • Just a controller, which is triggered when something happens in the application (this part is working fine and also quite irrelevant). I put together the required parameters for the endpoint and create a soap message to call it. The question is whether there is a better type for xml data on the xsd level before creating the JAXB classes, or a better way to turn xml data into string. – sticky_elbows Aug 30 '18 at 12:43

2 Answers2

1

You can't set it as XML without modifying your WSDL to handle the schema of your XML file IMHO.

There is three options:

1, modify your WSDL and integrate your XML file's schema into it, then when create the SOAP request, copy the content of your XML file to the request (I mean not as string, parse it and build up the whole file from node to node (or try to deserialize the complextype of the root element that should be defined in the WSDL/XSD of the WSDL too, however this is really not easy to get it work) in the SOAP request).

2, modify your WSDL, enable MTOM and add your file as attachment (this is the most efficient way to upload it, and your encoding I think will be safe)

3, use the original WSDL, if you have an xs:string field for your xml, read the whole xml to a String (as you did it in your post) then Base64 encode it (with some defined encoding) and in the server stub decode it using the same defined encoding.

m4gic
  • 1,461
  • 12
  • 19
  • However the third option is not too efficient for large files I would not recommend. – m4gic Aug 30 '18 at 12:54
  • Thank you for the answer. I like the 3rd option actually :) Could you give an example how to Base64 encode a string and keep it as string? – sticky_elbows Aug 30 '18 at 13:01
  • [Here](https://www.javaworld.com/article/3240006/java-language/base64-encoding-and-decoding-in-java-8.html) you are (assuming you are using java8) – m4gic Aug 30 '18 at 13:03
  • Thank you very much. upvoting for your efforts. – sticky_elbows Aug 30 '18 at 13:21
0

Found the solution as suggested by @ma4gic 3rd option. There was actually no need to remove any characters from the original xml file which was turned into String and also <xs:element name="xmlData" type="xs:string" /> is fine on the xsd level.

So first step is to turn xml into byteArray then encode it with Base64 in the caller:

File xmlDocument = new File("path/to/file.xml");
            byte[] binaryData = FileUtils.readFileToByteArray(xmlDocument);
            String xmlDataEncoded = org.apache.commons.codec.binary.Base64.encodeBase64String(binaryData);

then pass xmlDataEncoded to the web service in the SOAPMessage, and access the passed data in the web service like this:

@PayloadRoot(localPart="producepdf-request", namespace="http://www.my.com/name/space/model/")
@ResponsePayload
public ProducepdfResponse producePdf(@RequestPayload ProducepdfRequest document) throws IOException {

     byte[] incomingBinary = org.apache.commons.codec.binary.Base64.decodeBase64(document.getXmlData());
     String incomingDataRaw = new String(incomingBinary, "UTF-8");
    //do your stuff with the data
}
sticky_elbows
  • 1,344
  • 1
  • 16
  • 30