MULE ESB Simple SOAP service create mandatory fields - java

I want to expose a Simple SOAP web service in Mule 3.4 Community.
Some fields of the service need to be mandatory/required. How can that be done?
Here is the web service method:
public String methodname(String field1, String field2, String field3);
Here is the resulting wsdl:
<xsd:element minOccurs="0" name="field1" nillable="true" type="xsd:string"/>
<xsd:element minOccurs="0" name="field2" nillable="true" type="xsd:string"/>
<xsd:element minOccurs="0" name="field3" nillable="true" type="xsd:string"/>
How can I make these fields minOccurs="1" and nillable="false"
Please note #XmlElement(required=true) doesn't work with my Java version 1.6

minOccurs="1" makes the element mandatory and minOccurs="0" makes it optional
So make the following change to make it mandatory:-
<xsd:element minOccurs="1" name="field1" nillable="true" type="xsd:string"/>
<xsd:element minOccurs="1" name="field2" nillable="true" type="xsd:string"/>
<xsd:element minOccurs="1" name="field3" nillable="true" type="xsd:string"/>
For your reference :- https://social.msdn.microsoft.com/Forums/en-US/f59a3ee2-5997-4ee7-8c09-8d371c923267/creating-required-elements-in-xsd?forum=xmlandnetfx
and
How to tell if XML element is marked as required in the XSD file
and nillable is specifies whether an explicit null value can be assigned to the element
reference:-http://www.w3schools.com/schema/el_element.asp
So you need to make change in your WSDL so that the Java class generated from to implements those properties of attributes

I'm afraid you can't do this with a simple service (as it's simple by definition, it would probably work latter versions of java as you point).
You should switch to a fullfeatured jaxws service without autogenerated wdsl.

Related

Retrieve DelegateGroups and accounts associated with those groups from Salesforce

I am trying to bring in a set of groups called: DelegateGroup - Salesforce defines it as follows: DelegatedGroups
The meta data supplied shows the following:
<xsd:complexType name="DelegateGroup">
<xsd:complexContent>
<xsd:extension base="tns:Metadata">
<xsd:sequence>
<xsd:element name="customObjects" minOccurs="0" maxOccurs="unbounded" type="xsd:string"/>
<xsd:element name="groups" minOccurs="0" maxOccurs="unbounded" type="xsd:string"/>
<xsd:element name="label" type="xsd:string"/>
<xsd:element name="loginAccess" type="xsd:boolean"/>
<xsd:element name="permissionSets" minOccurs="0" maxOccurs="unbounded" type="xsd:string"/>
<xsd:element name="profiles" minOccurs="0" maxOccurs="unbounded" type="xsd:string"/>
<xsd:element name="roles" minOccurs="0" maxOccurs="unbounded" type="xsd:string"/>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
However this wasn't introduced until v36 so I went in and upgraded the Soap stubs to v46 - I am able to pull data from Salesforce, but I haven't figured out how to retrieve the DelegateGroup or how the accounts are associated with the delegategroup.
Note: The reason for the java tag is because I am coding this in Java.
Delegated Administrators can't be retrieved/deployed via metadata api. I think at best you'll get group names/permissions but not who's actually assigned. We know DelegateGroup and DelegateGroupMember objects exist (you can find them in online lists of obscure Salesforce object id prefixes) but they aren't exposed via API. See also https://salesforce.stackexchange.com/questions/129/querying-delegated-administrators

JAXB Map with abstract class values

I have the following Map that contains either Double or Integer instances as value, both of which extend the abstract class Number, annotated as follows:
#XmlElement(name="settings")
private Map<String,Number> settings;
It's marshalled into XML as:
<settings>
<entry>
<key>SETTING_A</key>
<value xsi:type="xs:double">0.03</value>
</entry>
<entry>
<key>SETTING_B</key>
<value xsi:type="xs:int">1000</value>
</entry>
</settings>
I also need to provide the XSD for this type of XML, and here is where I have problems. I tried to define a complexType with a choice, but doesn't work because the element that contain the int, and the element that contains the double can't have the same name (ie. they can't be both named "value"), which is exactly what the JAXB generated XML does.
The following XSD would work, but I don't want to have different element names ( or ):
<xsd:complexType name="Entry">
<xsd:sequence>
<xsd:element name="key" type="NimrodSettingKey" minOccurs="1" maxOccurs="1"/>
<xsd:choice>
<xsd:element name="double" type="xsd:double" minOccurs="1" maxOccurs="1"/>
<xsd:element name="int" type="xsd:integer" minOccurs="1" maxOccurs="1"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
Any suggestions on how should I specify that the element could be an int or a double in my XSD document?
Thanks!
EDIT #1
#svasa suggested using the following approach in my XSD, which give the same name to an element inside a choice:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Settings"/>
<xsd:complexType name="Settings">
<xsd:sequence>
<xsd:element name="key" type="xsd:string" minOccurs="1" maxOccurs="1" />
<xsd:choice>
<xsd:element name="value" xs:type="xsi:double" minOccurs="1" maxOccurs="1" />
<xsd:element name="value" xs:type="xsi:integer" minOccurs="1" maxOccurs="1" />
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
but my XSD editor complained with this error:
complex type 'Settings' violates the unique particle attribution rule in its components 'value' and 'value'
which I think means that the two elements under the must have different names each, they can't both be named "value".
I finally opted for refactoring my code from:
#XmlElement(name="settings")
private Map<String,Number> settings
to:
#XmlElementWrapper(name="settings")
#XmlElement(name="setting")
private List<Setting> settings;
My Settings class was renamed to Setting and now stores one single setting with attributes:
#XmlAttribute(name="name")
private String name;
#XmlAttribute(name="intValue")
private Integer intValue;
#XmlAttribute(name="doubleValue")
private Double doubleValue;
And when marshalled into XML, it produces the elements that either have doubleValue or intValue attributes (but the element is named in both cases):
<settings>
<setting name="SETTING_A" doubleValue="1.0E-5"/>
<setting name="SETTING_B" intValue="1000"/>
...
</settings>
And the XML generated is valid when the XSD contains:
<xsd:complexType name="Settings">
<xsd:sequence>
<xsd:element name="setting" type="Setting" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Setting">
<xsd:attribute name="name" type="xsd:string"/>
<xsd:attribute name="doubleValue" type="xsd:double"/>
<xsd:attribute name="intValue" type="xsd:int"/>
</xsd:complexType>
The xs:choice should enable you to specify integer or double, and maxOccurs="1" will take care of only one value.
But if you want the key to be unique, you could use xsd:unique like below:
<xsd:element name="settings">
<xsd:complexType>
<xsd:sequence>
<xsd:element maxOccurs="unbounded" name="entry">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="key" type="NimrodSettingKey" minOccurs="1" maxOccurs="1" />
<xsd:choice>
<xsd:element name="value" xsi:type="xsd:double" minOccurs="1" maxOccurs="1" />
<xsd:element name="value" xsi:type="xsd:integer" minOccurs="1" maxOccurs="1" />
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:unique name="keyU">
<xsd:selector xpath=".//key" />
<xsd:field xpath="." />
</xsd:unique>
</xsd:element>
This section :
<xsd:unique name="keyU">
<xsd:selector xpath=".//key" />
<xsd:field xpath="." />
</xsd:unique>
adds an unique constraint that specifies your keys should be unique.

CXF: generated WSDL vs. original WSDL

I have a question regarding WSDLs generated from CXF. From what I understood is that the WSDL that’s published by CXF is generated from JAX-WS/JAXB.
I have a WSDL file with the following content:
...
<xsd:complexType name="Scenario" mixed="true">
<xsd:sequence>
<xsd:element name="Description" type="xsd:anyURI" minOccurs="0"/>
<xsd:any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
</xsd:sequence>
<xsd:anyAttribute namespace="##other" processContents="lax"/>
</xsd:complexType>
...
After I generated my classes and deployed the service I checked the interface in my browser (with ?wsdl). Much to my surprise it looked considerably different: a "choice" has been added, processContents is changed, etc.
...
<xsd:complexType mixed="true" name="Scenario">
<xsd:sequence>
<xsd:choice maxOccurs="unbounded" minOccurs="0">
<xsd:element name="Description" type="xsd:string"/>
<xsd:any namespace="##other" processContents="lax"/>
<xsd:choice>
</xsd:sequence>
<xsd:anyAttribute namespace="##other" processContents="skip"/>
</xsd:complexType>
...
I am especially interested in this additional choice that’s been added?
Is it maybe because of the "xsd:any"?

some noob wsdl questions

<xsd:element name="loginResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="loginReturn" type="tns:test"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="test">
<xsd:sequence>
<xsd:element minOccurs="0" maxOccurs="1" name="tx" type="xsd:int"/>
<xsd:element minOccurs="0" maxOccurs="1" name="result" type="xsd:int"/>
<xsd:element minOccurs="0" maxOccurs="1" name="name_space" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
I just want to ask why is the type tns:test used? How can I get the tx, result, namespace values in complextype name="test", because that's the response should I get based on the api they given to me.
tns is the target namespace prefix, which should be defined at the top of your WSDL or XSD file (which includes test).
You didn't wrote how you do access the values, but I assume that your code is working in a different namespace, so that test cannot be indentified. Most likely there is a method which allows you to get values by element name and namespace. Note that in that case, the namespace isn't tns but rather the URL which is defined at top of source file.
If you're not familiar with namespaces: Each XML element is associated with a namespace, like a class in Java is part of a package. In XML there is no import statement, so you have to name an element by name and namespace. To keep the files readable you can define namespace prefixes (probably as an abbreviation).

JAXB DOM Node unmarshalling omits elements

I'm unmarshalling some XML from OGC and running into a problem where not all of the elements make it into the final object.
Here is the example XML
<?xml version="1.0"?>
<wfs:CreateStoredQuery xmlns:wfs="http://www.opengis.net/wfs/2.0"
xmlns:fes="http://www.opengis.org/fes/2.0" xmlns:gml="http://www.opengis.net/gml/3.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:myns="http://www.someserver.com/myns"
xsi:schemaLocation="http://www.opengis.net/wfs/2.0
http://schemas.opengis.net/wfs/2.0/wfs.xsd"
service="WFS" version="2.0.0">
<wfs:StoredQueryDefinition id="urn:StoredQueries:FeaturesInPolygon">
<wfs:Title>Features In Polygon</wfs:Title>
<wfs:Abstract>Find all the features in a Polygon.</wfs:Abstract>
<wfs:Parameter name="AreaOfInterest" type="gml:PolygonType" />
<wfs:QueryExpressionText returnFeatureTypes="myns:Parks"
language="urn:ogc:def:queryLanguage:OGC-WFS::WFS_QueryExpression"
isPrivate="false">
<wfs:Query typeNames="myns:Parks">
<fes:Filter>
<fes:Within>
<fes:ValueReference>geometry</fes:ValueReference>
<gml:Polygon>
<gml:exterior>
<gml:LinearRing>
<gml:posList>0 0 100 0 100 100 0 100 0 0</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</fes:Within>
</fes:Filter>
</wfs:Query>
</wfs:QueryExpressionText>
</wfs:StoredQueryDefinition>
</wfs:CreateStoredQuery>
Here is the XSD for the offending region
<xsd:complexType name="StoredQueryDescriptionType">
<xsd:sequence>
<xsd:element ref="wfs:Title" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element ref="wfs:Abstract" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element ref="ows:Metadata" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="Parameter"
type="wfs:ParameterExpressionType"
minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="QueryExpressionText"
type="wfs:QueryExpressionTextType"
minOccurs="1" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:anyURI" use="required"/>
</xsd:complexType>
<xsd:complexType name="ParameterExpressionType">
<xsd:sequence>
<xsd:element ref="wfs:Title" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element ref="wfs:Abstract" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element ref="ows:Metadata" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required"/>
<xsd:attribute name="type" type="xsd:QName" use="required"/>
</xsd:complexType>
<xsd:complexType name="QueryExpressionTextType" mixed="true">
<xsd:choice>
<xsd:any namespace="##other" processContents="skip"
minOccurs="0" maxOccurs="unbounded"/>
<xsd:any namespace="##targetNamespace" processContents="skip"
minOccurs="0" maxOccurs="unbounded"/>
</xsd:choice>
<xsd:attribute name="returnFeatureTypes"
type="wfs:ReturnFeatureTypesListType" use="required"/>
<xsd:attribute name="language" type="xsd:anyURI" use="required"/>
<xsd:attribute name="isPrivate" type="xsd:boolean" default="false"/>
</xsd:complexType>
<xsd:simpleType name="ReturnFeatureTypesListType">
<xsd:list itemType="xsd:QName"/>
</xsd:simpleType>
The part that is messing up is the xsd:any under QueryExpressionTextType. It has the attribute processContents="skip" which causes JAXB to create DOM objects instead of the JAXB classes. I figured I would just use the JAXB context to unmarshall the DOM Nodes afterwards, here is some example code for what I tried.
public static void main(String[] args) throws Exception {
InputStream in = new FileInputStream("test/res/createQuery.xml");
JAXBContext context = JAXBContext.newInstance(
net.opengis.gml.v_3_2_1.ObjectFactory.class,
net.opengis.wfs.v_2_0_0.ObjectFactory.class,
net.opengis.filter.v_2_0_0.ObjectFactory.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
JAXBElement<?> jElem = (JAXBElement<?>) unmarshaller.unmarshal(in);
CreateStoredQueryType create = (CreateStoredQueryType) jElem.getValue();
List<StoredQueryDescriptionType> descriptions = create
.getStoredQueryDefinition();
StoredQueryDescriptionType desc = descriptions.get(0);
List<QueryExpressionTextType> texts = desc.getQueryExpressionText();
QueryExpressionTextType text = texts.get(0);
List<Object> contents = text.getContent();
Node node = (Node) contents.get(0);
jElem = (JAXBElement<?>) unmarshaller.unmarshal(node);
QueryType query = (QueryType) jElem.getValue();
// prints[{http://www.someserver.com/myns}Parks]
System.out.println(query.getTypeNames());
// is false
System.out.println(query.isSetAbstractSelectionClause());
}
It gets the Query object out just fine (including the typeNames attribute). But it skips the Filter object. The Filter object inherits from AbstractSelectionClause, so it should be set in the returned object, but it isn't. I debugged and checked the DOM Element and confirmed that the Filter is in the DOM tree.
To get the JAXB objects I'm using, I checked out the SVN repository from the jvnet OGC project, I did have to compile the WFS 2.0 schemas, but the Filter and GML schemas were already done.
Any insight would be greatly appreciated.
The example XML came from the OGC WFS 2.0 specification document (09-025r1) on page 81. There is a typo that has the xmlns for Filter as "http://www.opengis.org/fes/2.0" when is should be "http://www.opengis.net/fes/2.0". JAXB was seeing this as an unrecognized element and dropping it on the floor.

Categories