I implemented a working web service using CXF (2.7.1) with a WSDL & XSD that include, among other things, the following type:
<xs:simpleType name="SimpleIdType">
<xs:restriction base="xs:string">
<xs:pattern value="[A-Za-z0-9:\.\-]{20}"/>
</xs:restriction>
</xs:simpleType>
I interpret this to be: Accept only 20 character strings which only contain alphanumeric characaters and ':', '.' and '-'.
When I send a SOAP message to my web service with the corresponding element containing FAAAAAAAAAAAAAAAAAAA, the service of course accepts properly without any error.
However, if I send an identical SOAP message with the # instead of F (i.e. #AAAAAAAAAAAAAAAAAAA), the service still accepts the message, without issuing any validation error (unmarshalling or otherwise).
Why?
Isn't the default ValidationEventHandler supposed to handle that by throwing an "Unmarshalling Error"?
The JAXB model (generated or hand coded) does not contain all the metadata from the XML schema in its annotations. If you want to validate against all aspects of the schema you can enable this be specifying an instance of Schema on the Unmarshaller.
http://blog.bdoughan.com/2010/12/jaxb-and-marshalunmarshal-schema.html
I finally found the correct answer for this CXF-based case.
CXF already has runtime schema validation built-in. It is named schema validation via configuration and the only thing that was missing in my code was the XML to enable it, inside the already existing <jaxws:endpoint element in beans.xml AKA application-context.xml:
<jaxws:properties>
<entry key="schema-validation-enabled" value="true" />
</jaxws:properties>
This discovery was made possible thanks to the answer by #Patrick.
Related
This is an extension question to How to use SpEL to read payload and header content in a Spring Integration Router
Technologies in my project
Spring Boot 2
Spring Integration (XML style)
Java 8
Tomcat 9.x/Liberty 19.0.0.1
As a part of my Spring Integration project (REST API with an inbound-http-gateway, that takes an XML input and produces an XML output), this is the setup for my question:
There is a Builder-pattern-based Java object (say, MyPOJO) that is the payload in the flow.
MyPOJO has a String property/instance variable (say, String response) along with a getter and setter.
Somewhere in the flow, MyPOJO gets built and response gets set.
Inside response, there is a keyword/specific piece of text that will determine the further course of the flow.
This said, is it possible to write a Router (using XML configuration) that can check if the response inside Message<MyPOJO> contains that keyword/specific piece of text to determine where to go next?
Illustratively, something like this:
<int:router input-channel="inputChannel" expression="payload.getResponse().contains("keyword")">
<int:mapping value="true" channel="oneRoute"/>
<int:mapping value="false" channel="anotherRoute"/>
</int:router>
When I do this and launch the application, the error is:
nested exception is org.xml.sax.SAXParseException; lineNumber: 44; columnNumber: 98; Element type "int:router" must be followed by either attribute specifications, ">" or "/>"
Specifically speaking, the expression="payload.getResponse().contains("keyword")" part seems to be having an issue getting resolved and this could be something to do with the quotation marks around the keyword
Any help on this is greatly appreciated.
Sincerely,
Bharath
OK. I see you have an XML syntax error. The fix is like this:
expression="payload.getResponse().contains('keyword')"
The keyword is in single quotes, not double.
This is definitely how SpEL works: when you would like to specify a literal in the expression, you need to use single quotes: https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#expressions-evaluation
I need to create a Mock Service for EWS and I have gotten hold of the WSDL file and .XSD from the Exchange server endpoint (I am logged with my credentials)
https://outlook.office365.com/EWS/Services.wsdl
https://outlook.office365.com/EWS/Messages.xsd
https://outlook.office365.com/EWS/Types.xsd
I have created a project in SOAP UI and when I generated a Mock Service only the following WSDL operations's responses are mocked:
AddDelegate
AddDistributionGroupToImList
AddImContactToGroup
AddImGroup
AddNewImContactToGroup
AddNewTelUriContactToGroup
AddTag
At a closer look and testing the validity of the WSDL as well as the .XSDs, the following errors are highlighted:
Services.wsdl: "
Referenced file contains errors (file:/pathToFile/types.xsd).
I then look at the error in types.xsd and it seems to point to the attribute in:
<xs:complexType name="ReplyBody">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="Message" type="xs:string"/>
</xs:sequence>
<xs:attribute ref="xml:lang" use="optional"/>
</xs:complexType>
with the following error message (I am validating within Eclipse Neon):
Multiple annotations found at this line:
- s4s-elt-invalid-content.1: The content of 'ReplyBody' is invalid. Element 'attribute' is invalid, misplaced, or occurs too often.
- src-resolve: Cannot resolve the name 'xml:lang' to a(n) 'attribute declaration' component.
I have tried to remove that attribute, but the issue remains. Am I missing anything obvious?
Can you please help?
Thanks,
I.
EDIT 1
My main concern is that I am possibly going completely wrong in the way I am getting hold of the EWS WSDL and schemas. Is that the right way to do it?
EDIT 2
I have also try to import the WSDL directly from the URL and I am returned with the same missing operations.
The default for minOccurs property of an <element> in an XSD file is 1 (source).
Consider you have an XSD specifying a complex type containing 2 elements: <el1> and <el2>.
If you provide an XDocument only containing <el2>, the XDocument will not validate.
Instead you'll get the message:
The element Message in namespace ___ has invalid child element el2 in namespace ___.
List of possible elements expected: el1
This basically is an error on <el2> where one would expect an error on the complex type for not containing <el1>.
My question is:
Is there a way to check if all <element>-tags which have minOccurs > 0 are present?
I would say this is a very basic check when validating XML with an XSD.
Depending on the way you defined your schema, the order of appearance of elements will matter.
In this case the validator is expecting a <el1> but is seeing the element <el2> so the error is that <el2> is appearing where it should not. I belive that means you used a "sequence" when defining your complex type. So the error you at getting is correct.
If this still bothers you, and the order of the elements does not matter to your parsing use "all" instead of "sequence" which will not enforce order. The validator should then prompt you that a required element <el1> is missing. It should look something like the following:
<xsd:complexType name="MyType">
<xsd:all>
<xsd:element name="el1" minOccurs="1"/>
<xsd:element name="el2" minOccurs="1"/>
</xsd:all>
</xsd:complexType>
I hope this helps.
I'm using JAXB 2.1.10 from Sun's JDK 1.6.0_18:
D:\apps\jdk160_18\bin>xjc.exe -version
xjc version "JAXB 2.1.10 in JDK 6"
JavaTM Architecture for XML Binding(JAXB) Reference Implementation, (build JAXB 2.1.10 in JDK 6)
I need to have JAXB's marshaller produce an empty element (e.g. <someStringField></someStringField> or <someStringField/>) when the JAXB object has the value of the empty string (""). However, rather than doing that, JAXB omits the element altogether from its output (as if it where an optional element).
My searches in the Internet indicated that JAXB should normally create this tag, as long as you set the field to the non-null empty string (i.e. myJAXBObject.setSomeStringField(""); ):
How to instantiate an empty element with JAXB
https://jaxb.dev.java.net/tutorial/section_2_2_12_8-No-Value.html#No%20Value
In my XSD, I've tried to indicate (in every way I know) that the element's presence is mandatory even if it is empty:
<xs:element name="outerElement">
<xs:complexType>
<xs:sequence>
<xs:element name="someStringField" type="xs:string" nillable="false" minOccurs="1" />
<xs:element name="someOtherStringField" type="xs:string" />
The generated code looks like this (it's the same for both elements):
#XmlElement(name = "someStringField", required = true)
protected String someStringField;
#XmlElement(name = "someOtherStringField", required = true)
protected String someOtherStringField;
However, when I marshal the following object...
outerElement.setSomeStringField("");
outerElement.setSomeOtherStringField("Value was set");
I get:
<outerElement>
<someOtherStringField>Value was set</someOtherStringField>
</outerElement>
When I was expecting:
<outerElement>
<someStringField></someStringField>
<someOtherStringField>Value was set</someOtherStringField>
</outerElement>
Or:
<outerElement>
<someStringField/>
<someOtherStringField>Value was set</someOtherStringField>
</outerElement>
Can anyone spot what I'm doing wrong?
Thank you for bringing this issue (https://bugs.eclipse.org/319028) to our attention. The bug has been fixed and will be included in the EclipseLink 2.1.1 maintenance release. If you want access to this fix earlier you can pick up the nightly download starting July 8th from:
http://www.eclipse.org/eclipselink/downloads/nightly.php
Apologies. I THOUGHT I was using JAXB from Sun's JDK, but I wasn't. There was a left-over jaxb.properties in my classes/ folder that was created by JDeveloper when I generated the bindings. I was actually using JAXB2.0 from EclipseLink/MOXy.
Removing the properties file allowed JAXB2.1 to be used and fixed my issue.
I have a .xsd file which I use to generate code with the xsd.exe tool from Visual Studio.
Some class members are Guids and the xsd.exe tool gives 2 warnings:
Namespace 'http://microsoft.com/wsdl/types/' is not available to be referenced in this schema.
Type 'http://microsoft.com/wsdl/types/:guid' is not declared.
The Guid type is recognized because the generated C# file is valid and works.
Anyone knows how to get rid of those warnings?
What is the correct syntax for the XSD to be validated AND class members being generated as System.Guid?
Thank you all,
I found how to remove the warnings.
As sysrqb said, the wsdl namespace has either been deleted or never existed. It seems that the xsd.exe tool knows the Guid definition internally, but it cannot validate the xsd schema.
As boj pointed out, the only way to validate the schema with Guids in it, is to (re)define that type in a schema. The trick here is to add the Guid type to the same "http://microsoft.com/wsdl/types" namespace. This way, the xsd.exe will do the proper association between http://microsoft.com/wsdl/types:Guid and System.Guid
I made a new xsd file for the guid type:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://microsoft.com/wsdl/types/" >
<xs:simpleType name="guid">
<xs:annotation>
<xs:documentation xml:lang="en">
The representation of a GUID, generally the id of an element.
</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:pattern value="\{[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}\}"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
Then, I run xsd.exe with both my original xsd file and this new xsd file:
xsd.exe myschema.xsd guid.xsd /c
Citation from here:
XmlSchema guidSchema = new XmlSchema();
guidSchema.TargetNamespace = "http://microsoft.com/wsdl/types/";
XmlSchemaSimpleTypeRestriction guidRestriction = new XmlSchemaSimpleTypeRestriction();
guidRestriction.BaseTypeName = new XmlQualifiedName("string", XmlSchema.Namespace);
XmlSchemaPatternFacet guidPattern = new XmlSchemaPatternFacet();
guidPattern.Value = #"[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}";
guidRestriction.Facets.Add(guidPattern);
XmlSchemaSimpleType guidType = new XmlSchemaSimpleType();
guidType.Name = "guid";
guidType.Content = guidRestriction;
guidSchema.Items.Add(guidType);
schemaSet.Add(guidSchema);
XmlSchema speakerSchema = new XmlSchema();
speakerSchema.TargetNamespace = "http://www.microsoft.com/events/teched2005/";
// ...
XmlSchemaElement idElement = new XmlSchemaElement();
idElement.Name = "ID";
// Here's where the magic happens...
idElement.SchemaTypeName = new XmlQualifiedName("guid", "http://microsoft.com/wsdl/types/");
It looks like that wsdl namespace extension page was deleted, so it can't find the type information you need.