Adding complex object to SOAP Response - object

I sent my complex objects to the Request like :
this
now I want to getting complex objects from the Response.
The following is a sample SOAP 1.1 response :
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<CommitReceiptionAgentResponse xmlns="http://mywebService.ir/">
<CommitReceiptionAgentResult Exc="string">
<Errors>
<string>string</string>
<string>string</string>
</Errors>
<CST>dateTime</CST>
</CommitReceiptionAgentResult>
</CommitReceiptionAgentResponse>
</soap:Body>
</soap:Envelope>
I created CommitReceiptionAgentResponse Class :
public class CommitReceiptionAgentResponse implements KvmSerializable {
#Element(name = "CommitReceiptionAgentResult")
CommitReceiptionAgentResult commitReceiptionAgentResult;
.
.
.
}
and I created CommitReceiptionAgentResult Class too :
public class CommitReceiptionAgentResult extends Vector<String> implements KvmSerializable {
#ElementList(name = "Errors")
public Errors errors;
#Attribute(name = "Exc", required = false)
public String InternalServiceException;
#Element(name = "CST", required = false)
public Date CommitStartTime;
.
.
.
}
that getProperty() method of CommitReceiptionAgentResult class defined as blew :
#Override
public Object getProperty(int arg0) {
switch (arg0) {
case 0:
Errors errorList = getErrors();
SoapObject erlistObject = new SoapObject(
ServiceUtil.WSDL_TARGET_NAMESPACE, "errorList");
try{
if (errorList.size() > 0) {
for (String error : errorList) {
SoapObject erObject = new SoapObject(
ServiceUtil.WSDL_TARGET_NAMESPACE, "Errors");
PropertyInfo info = new PropertyInfo();
errorList.getPropertyInfo(0, null, info);
erObject.addProperty(info.name,
errorList.getProperty(0));
erlistObject.addSoapObject(erObject);
}
}
}catch (Exception e) {
}
return erlistObject;
case 1:
return getInternalServiceException();
case 2:
return getCommitStartTime();
}
return null;
}
#Element(name = "CST", required = false)
public Date CommitStartTime;
}
and I create Errors class like this :
public class Errors extends Vector<String> implements KvmSerializable{
#Override
public Object getProperty(int arg0) {
return this.get(arg0);
}
#Override
public int getPropertyCount() {
return 1;
}
#Override
public void getPropertyInfo(int arg0, Hashtable arg1, PropertyInfo arg2) {
arg2.name = "string";
arg2.type = PropertyInfo.STRING_CLASS;
}
#Override
public void setProperty(int arg0, Object arg1) {
this.add(arg1.toString());
}
}
When I define soap Objects and envelope according to
this link
and
this
, envelope.getResponse() is null :
final SoapObject response1 = new SoapObject(WSDL_TARGET_NAMESPACE,
"CommitReceiptionAgentResponse");
response1.addProperty("CommitReceiptionAgentResult",
new CommitReceiptionAgentResult());
final SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
envelope.bodyOut = request;
envelope.setOutputSoapObject(response1);
envelope.addMapping(WSDL_TARGET_NAMESPACE,
"CommitReceiptionAgentResponse",
new CommitReceiptionAgentResponse().getClass());
envelope.addMapping(WSDL_TARGET_NAMESPACE,
"CommitReceiptionAgentResult",
new CommitReceiptionAgentResult().getClass());
envelope.addMapping(WSDL_TARGET_NAMESPACE, "Errors",
new Errors().getClass());
HttpTransportSE httpTransport1 = new HttpTransportSE(SOAP_ADDRESS);
try {
httpTransport1.debug = true;
httpTransport1.setXmlVersionTag("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
httpTransport1.call(SOAP_ACTION, envelope); // in/out
SoapObject response = (SoapObject) soapEnvelope.getResponse();
}catch(exception){}
I searched a lots, but could not find the problem.
I want to know my implementation of classes and addMAppings Is 'true'?! If it is wrong what is the currect answer.
I will be appreciate if any one help me.
Thanks in advance
Excuse me for my english.

Related

How to persist UserData of Element in JAXB Unmarshal?

I unmarshal the Document to object as below.
Before that, when parsing XML, use setUserData to store location information for each element.
class MyJaxbAdapter extends XmlAdapter<Object, SubObject> {}
#Override
public UnattendComponent unmarshal(Object v) throws Exception {
Node node = (Node) v; // ElementNSImpl; It's probably a newly created object. Because It is different from the document object given by ownerDocument as SAXSource.
node.getUserData(...) // return NULL
}
}
Document document = ...;
unmarshaller.setAdapter(new MyJaxbAdapter());
MyXMLObject object = unmarshaller.unmarshal(new DOMSource(document), MyXMLObject.class).getValue();
But I can't get UserData inside XmlAdapter's unmarshal method. Is there any way to persist UserData?
Locator information is stored in the properties of Element as shown below.
#Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
Element el = document.createElementNS(usedNamespaceUri, qName);
// ...
el.setUserData(
ElementUserData.class.getName(),
ElementUserData.builder()
.lineNumber(locator.getLineNumber())
.columnNumber(locator.getColumnNumber())
.build(),
null);
}
I need the Locator information (UserData) stored by the above code in the unmarshal of the XmlAdapter.
However, there is no userdata in the node passed as an argument to unmarshal .
Sample Code:
https://github.com/joseph-jclab/jaxb-question-01
Not entirely sure if this is something you are looking for but providing it as a reference so you might get some idea to proceed further:
Sample XML:
<root>
<name>Batman</name>
<year>2008</year>
</root>
Root.class:
#XmlRootElement(name = "root")
#Data
#XmlAccessorType(XmlAccessType.FIELD)
public class Root {
private String name;
private String year;
#XmlJavaTypeAdapter(CustomAdapter.class)
private String after;
private void afterUnmarshal(Unmarshaller m, Object parent) {
after = name;
}
}
CustomAdapter.class:
public class CustomAdapter extends XmlAdapter<String, String> {
#Override
public String unmarshal(String v) throws Exception {
System.out.println("Within Unmarshal : " + v);
return null;
}
#Override
public String marshal(String v) throws Exception {
System.out.println("Within Marshal : " + v);
return null;
}
}
SampleMain.class:
public class SampleMain {
public static void main(String[] args) throws XMLStreamException, JAXBException {
final InputStream inputStream = Unmarshalling.class.getClassLoader().getResourceAsStream("sample.xml");
final XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader(inputStream);
final Unmarshaller unmarshaller = JAXBContext.newInstance(Root.class).createUnmarshaller();
unmarshaller.setAdapter(new CustomAdapter());
final Root root = unmarshaller.unmarshal(xmlStreamReader, Root.class).getValue();
System.out.println(root.toString());
Marshaller marshaller = JAXBContext.newInstance(Root.class).createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(root, System.out);
}
}
Output:
Root(name=Batman, year=2008, after=Batman)
Within Marshal : Batman
<root>
<name>Batman</name>
<year>2008</year>
</root>

I Want To Itemonclicklister in Fragment on Spinner

This Is Main Fragment
Fragment:
private void getStock() {
dialog.show();
Retrofit retrofit = RetrofitClient.getRetrofitInstance();
apiInterface api = retrofit.create(apiInterface.class);
Call<List<Blocks>>call = api.getVaccineBlocks();
call.enqueue(new Callback<List<Blocks>>() {
#Override
public void onResponse(Call<List<Blocks>>call, Response<List<Blocks>> response) {
if (response.code() == 200) {
block = response.body();
spinnerada();
dialog.cancel();
}else{
dialog.cancel();
}
}
#Override
public void onFailure(Call<List<Blocks>> call, Throwable t) {
dialog.cancel();
}
});
}
private void spinnerada() {
String[] s = new String[block.size()];
for (int i = 0; i < block.size(); i++) {
s[i] = block.get(i).getBlockName();
final ArrayAdapter a = new ArrayAdapter(getContext(), android.R.layout.simple_spinner_item, s);
a.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
//Setting the ArrayAdapter data on the Spinner
spinner.setAdapter(a);
}
}
This Is Blocks Model
model:
package com.smmtn.book.models;
import java.io.Serializable;
public class Blocks implements Serializable {
public String id;
public String blockName;
public String blockSlug;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getBlockName() {
return blockName;
}
public void setBlockName(String blockName) {
this.blockName = blockName;
}
public String getBlockSlug() {
return blockSlug;
}
public void setBlockSlug(String blockSlug) {
this.blockSlug = blockSlug;
}
}
here i need onitemclick with blockslug please any one can help, am new to android so i need some example.when on click i want take blockslug and load another method with that blockslug,like will get data from u "http://example.com/block/"+blockslug
i want to get blockslug from selected block
i hope guys i will get help
and sorry for my bad English,
First of all, you need to implement setOnItemSelectedListener. Refer to this https://stackoverflow.com/a/20151596/9346054
Once you selected the item, you can call them by making a new method. Example like below
public void onItemSelected(AdapterView<?> parent, View view, int pos,long id) {
Toast.makeText(parent.getContext(),
"OnItemSelectedListener : " + parent.getItemAtPosition(pos).toString(),
Toast.LENGTH_SHORT).show();
final String itemSelected = parent.getItemAtPosition(pos).toString();
showBlockSlug(itemSelected);
}
And then, at the method showBlockSlug() , you can call Retrofit.
private void showBlockSlug(final String blockslug){
final String url = "http://example.com/block/"+ blockslug;
//Do your stuff...
}

JaxB representation for Object to support different types

Following java property can be of either String/Integer type. I tried adding annotation as below, but it would only take the last type(string in this case), even when an integer is passed. How can we allow multiple types for this property?
#XmlElements({
#XmlElement(type = Integer.class), #XmlElement(type = String.class)
})
private Object val1;
The problem is that there is no name to differentiate between the different type of classes when unmarshaling. I don't know what exactly are your requirements but this is how you could make it work:
#XmlRootElement(name = "root")
#XmlAccessorType(XmlAccessType.FIELD)
public class SomeRoot {
#XmlElements({
#XmlElement(name="string", type = String .class),
#XmlElement(name="int", type = Integer.class)
})
private Object val;
public SomeRoot(Object val) {
this.val = val;
}
public SomeRoot() { }
}
When you have a String value provided it would be marshaled into something like that:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<string>test</string>
</root>
And when given an Integer it would marshal into something like that:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<int>1</int>
</root>
Both of these would be unmarshaled to their proper type because of the difference in the element name.
Also if you would have a list of Objects you could marshal/unmarshal something like this with no problem:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<int>1</int>
<string>test1</string>
<string>test2</string>
<string>test3</string>
<int>3</int>
</root>
Update:
If you want both types under the <val> element, you could use a custom XmlAdapter to check on the type. This could look like this:
public class MyXmlAdapter extends XmlAdapter<Object, Object> {
private DocumentBuilder documentBuilder;
public MyXmlAdapter() {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
documentBuilder = dbf.newDocumentBuilder();
} catch(Exception e) {
// TODO - Handle Exception
}
}
#Override
public Object unmarshal(Object v) throws Exception {
Element element = (Element) v;
String elementValue = element.getTextContent();
if(StringUtils.isNumeric(elementValue)) {
return Integer.parseInt(elementValue);
} else {
return new String(elementValue);
}
}
#Override
public Object marshal(Object v) throws Exception {
return v;
}
}
And your root class would be something like this:
#XmlRootElement(name = "root")
#XmlAccessorType(XmlAccessType.FIELD)
public class SomeRoot {
#XmlJavaTypeAdapter(MyXmlAdapter.class)
private Object val;
public SomeRoot(Object val) {
this.val = val;
}
public SomeRoot() { }
public Object getVal() {
return val;
}
}
Trying this out in a simple main, resolves the provided xml to the right type for both String and Integer on val:
public static void main(String[] args) {
try {
File file = new File("file.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(SomeRoot.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
jaxbUnmarshaller.setAdapter(new MyXmlAdapter());
SomeRoot pojo = (SomeRoot) jaxbUnmarshaller.unmarshal(file);
System.out.println(pojo.getVal().getClass());
} catch (JAXBException e) {
e.printStackTrace();
}
}

Unmarshalling an XML document to Oracle Object Type using JAXB annotations

I am trying to unmarshal an XML document into an Oracle SQL Object Type.
Below is the sample XML :
<?xml version="1.0" encoding="UTF-8"?>
<order>
<ordernumber>123-01</ordernumber>
<customername>Idea Networks</customername>
<item>
<itemnumber>T-01</itemnumber>
<quantity>1</quantity>
<amount>10</amount>
</item>
<item>
<itemnumber>T-20</itemnumber>
<quantity>3</quantity>
<amount>8</amount>
</item>
</order>
Below is the definition of the oracle object type in oracle database :
CREATE OR REPLACE TYPE Item AS OBJECT
(
ItemNumber VARCHAR2(240)
,Quantity NUMBER
,Amount NUMBER
);
CREATE OR REPLACE TYPE ItemsArray IS TABLE OF Item;
CREATE OR REPLACE TYPE ItemOrder AS OBJECT
(
OrderNumber VARCHAR2(240)
,CustomerName VARCHAR2(240)
,Items ItemsArray
);
Now I used Jpublisher to generate the java classes for the object
java oracle.jpub.Doit -user=scott/tiger -sql=ItemOrder -package=xxcmpon.order.test
I have got total 5 classes generated (Item.java,ItemRef.java,ItemOrder.java,ItemOrderRef.java,Itemsarray.java)
The ItemOrder class looks as below :
package xxcmpon.order.test;
import java.sql.SQLException;
import java.sql.Connection;
import oracle.jdbc.OracleTypes;
import oracle.sql.ORAData;
import oracle.sql.ORADataFactory;
import oracle.sql.Datum;
import oracle.sql.STRUCT;
import oracle.jpub.runtime.MutableStruct;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
#XmlRootElement(name="order")
#XmlType(name = "ItemOrder", propOrder = {
"ordernumber",
"customername",
"items"
})
public class ItemOrder implements ORAData, ORADataFactory
{
public static final String _SQL_NAME = "SCOTT.ITEMORDER";
public static final int _SQL_TYPECODE = OracleTypes.STRUCT;
protected MutableStruct _struct;
protected static int[] _sqlType = { 12,12,2003 };
protected static ORADataFactory[] _factory = new ORADataFactory[3];
static
{
_factory[2] = Itemsarray.getORADataFactory();
}
protected static final ItemOrder _ItemOrderFactory = new ItemOrder();
public static ORADataFactory getORADataFactory()
{ return _ItemOrderFactory; }
/* constructors */
protected void _init_struct(boolean init)
{ if (init) _struct = new MutableStruct(new Object[3], _sqlType, _factory); }
public ItemOrder()
{ _init_struct(true); }
public ItemOrder(String ordernumber, String customername, Itemsarray items) throws SQLException
{ _init_struct(true);
setOrdernumber(ordernumber);
setCustomername(customername);
setItems(items);
}
/* ORAData interface */
public Datum toDatum(Connection c) throws SQLException
{
return _struct.toDatum(c, _SQL_NAME);
}
/* ORADataFactory interface */
public ORAData create(Datum d, int sqlType) throws SQLException
{ return create(null, d, sqlType); }
protected ORAData create(ItemOrder o, Datum d, int sqlType) throws SQLException
{
if (d == null) return null;
if (o == null) o = new ItemOrder();
o._struct = new MutableStruct((STRUCT) d, _sqlType, _factory);
return o;
}
/* accessor methods */
public String getOrdernumber() throws SQLException
{ return (String) _struct.getAttribute(0); }
public void setOrdernumber(String ordernumber) throws SQLException
{ _struct.setAttribute(0, ordernumber); }
public String getCustomername() throws SQLException
{ return (String) _struct.getAttribute(1); }
public void setCustomername(String customername) throws SQLException
{ _struct.setAttribute(1, customername); }
public Itemsarray getItems() throws SQLException
{ return (Itemsarray) _struct.getAttribute(2); }
public void setItems(Itemsarray items) throws SQLException
{ _struct.setAttribute(2, items); }
}
The Item class looks as below :
package xxcmpon.order.test;
import java.sql.SQLException;
import java.sql.Connection;
import oracle.jdbc.OracleTypes;
import oracle.sql.ORAData;
import oracle.sql.ORADataFactory;
import oracle.sql.Datum;
import oracle.sql.STRUCT;
import oracle.jpub.runtime.MutableStruct;
import javax.xml.bind.annotation.XmlType;
#XmlType(name = "Item", propOrder = {
"itemnumber",
"quantity",
"amount"
})
public class Item implements ORAData, ORADataFactory
{
public static final String _SQL_NAME = "SCOTT.ITEM";
public static final int _SQL_TYPECODE = OracleTypes.STRUCT;
protected MutableStruct _struct;
protected static int[] _sqlType = { 12,2,2 };
protected static ORADataFactory[] _factory = new ORADataFactory[3];
protected static final Item _ItemFactory = new Item();
public static ORADataFactory getORADataFactory()
{ return _ItemFactory; }
/* constructors */
protected void _init_struct(boolean init)
{ if (init) _struct = new MutableStruct(new Object[3], _sqlType, _factory); }
public Item()
{ _init_struct(true); }
public Item(String itemnumber, java.math.BigDecimal quantity, java.math.BigDecimal amount) throws SQLException
{ _init_struct(true);
setItemnumber(itemnumber);
setQuantity(quantity);
setAmount(amount);
}
/* ORAData interface */
public Datum toDatum(Connection c) throws SQLException
{
return _struct.toDatum(c, _SQL_NAME);
}
/* ORADataFactory interface */
public ORAData create(Datum d, int sqlType) throws SQLException
{ return create(null, d, sqlType); }
protected ORAData create(Item o, Datum d, int sqlType) throws SQLException
{
if (d == null) return null;
if (o == null) o = new Item();
o._struct = new MutableStruct((STRUCT) d, _sqlType, _factory);
return o;
}
/* accessor methods */
public String getItemnumber() throws SQLException
{ return (String) _struct.getAttribute(0); }
public void setItemnumber(String itemnumber) throws SQLException
{ _struct.setAttribute(0, itemnumber); }
public java.math.BigDecimal getQuantity() throws SQLException
{ return (java.math.BigDecimal) _struct.getAttribute(1); }
public void setQuantity(java.math.BigDecimal quantity) throws SQLException
{ _struct.setAttribute(1, quantity); }
public java.math.BigDecimal getAmount() throws SQLException
{ return (java.math.BigDecimal) _struct.getAttribute(2); }
public void setAmount(java.math.BigDecimal amount) throws SQLException
{ _struct.setAttribute(2, amount); }
}
The Itemsarray class looks as below :
package xxcmpon.order.test;
import java.sql.SQLException;
import java.sql.Connection;
import oracle.jdbc.OracleTypes;
import oracle.sql.ORAData;
import oracle.sql.ORADataFactory;
import oracle.sql.Datum;
import oracle.sql.ARRAY;
import oracle.sql.ArrayDescriptor;
import oracle.jpub.runtime.MutableArray;
import javax.xml.bind.annotation.XmlElement;
public class Itemsarray implements ORAData, ORADataFactory
{
public static final String _SQL_NAME = "SCOTT.ITEMSARRAY";
public static final int _SQL_TYPECODE = OracleTypes.ARRAY;
MutableArray _array;
private static final Itemsarray _ItemsarrayFactory = new Itemsarray();
public static ORADataFactory getORADataFactory()
{ return _ItemsarrayFactory; }
/* constructors */
public Itemsarray()
{
this((Item[])null);
}
public Itemsarray(Item[] a)
{
_array = new MutableArray(2002, a, Item.getORADataFactory());
}
/* ORAData interface */
public Datum toDatum(Connection c) throws SQLException
{
return _array.toDatum(c, _SQL_NAME);
}
/* ORADataFactory interface */
public ORAData create(Datum d, int sqlType) throws SQLException
{
if (d == null) return null;
Itemsarray a = new Itemsarray();
a._array = new MutableArray(2002, (ARRAY) d, Item.getORADataFactory());
return a;
}
public int length() throws SQLException
{
return _array.length();
}
public int getBaseType() throws SQLException
{
return _array.getBaseType();
}
public String getBaseTypeName() throws SQLException
{
return _array.getBaseTypeName();
}
public ArrayDescriptor getDescriptor() throws SQLException
{
return _array.getDescriptor();
}
/* array accessor methods */
public Item[] getArray() throws SQLException
{
return (Item[]) _array.getObjectArray(
new Item[_array.length()]);
}
public Item[] getArray(long index, int count) throws SQLException
{
return (Item[]) _array.getObjectArray(index,
new Item[_array.sliceLength(index, count)]);
}
public void setArray(Item[] a) throws SQLException
{
_array.setObjectArray(a);
}
public void setArray(Item[] a, long index) throws SQLException
{
_array.setObjectArray(a, index);
}
public Item getElement(long index) throws SQLException
{
return (Item) _array.getObjectElement(index);
}
public void setElement(Item a, long index) throws SQLException
{
_array.setObjectElement(a, index);
}
}
To the above classes I have added the JAXB annotations for reading the XML document.
I am trying to unmarshal the xml document and print it through a sample script as shown below :
public class Main {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(ItemOrder.class);
Unmarshaller u = jc.createUnmarshaller();
Marshaller m = jc.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
try {
ItemOrder orderx = (ItemOrder)u.unmarshal(new FileInputStream("order.xml"));
Itemsarray items = orderx.getItems();
System.out.println("Order Number : " + orderx.getOrdernumber());
//Item[] itemo = items.getArray();
//System.out.println("Item Number : " + itemo[0].getItemnumber());
m.marshal(orderx, System.out);
} catch(javax.xml.bind.UnmarshalException e){
System.out.println("Main: " + e);
} catch(Exception e1){
System.out.println("Main: " + e1);
e1.printStackTrace();
}
}
}
[ttr12#rstnssiovm0015 test]$ java xxcmpon.order.test.Main
Order Number : 123-01
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<order>
<ordernumber>123-01</ordernumber>
<customername>Idea Networks</customername>
</order>
[ttr12#rstnssiovm0015 test]$
I am expecting the output to be displayed with the items as shown below :
<?xml version="1.0" encoding="UTF-8"?>
<order>
<ordernumber>123-01</ordernumber>
<customername>Idea Networks</customername>
<item>
<itemnumber>T-01</itemnumber>
<quantity>1</quantity>
<amount>10</amount>
</item>
<item>
<itemnumber>T-20</itemnumber>
<quantity>3</quantity>
<amount>8</amount>
</item>
</order>
I think I am missing some annotation to bind the items array, which I am not able figure out.
Can somebody please let me know what is the annotation I am missing and where to add that?
Thanks for your help.
I would suggest you to prepare the ItemOrder object with several Item's in it programmatically and then marshal it to the standard output. The marshaled XML will obviously different from one you created manually. It will give you an idea, what is wrong with your original XML.
You, presumably will be able to unmarshal that XML back into the Java- class without any problem.

JAX-WS custom object received in request is null

I've used JAX-WS before, but have not passed a custom object as a parameter before. I'm using GlassFish 3.1, NetBeans 7.3 and created services through NetBeans JAX-WS wizard.
My problem is when custom object (Criteria) passed to service is received as null on the server. I can pass default types like int successfully.
#WebService(serviceName = "ECLService")
#Stateless()
public class ECLService {
#EJB
PersistenceImpl persistence;
#WebMethod(operationName = "listRevisions")
public List<Revision> listRevisions(#WebParam(name="criteria")Criteria criteria) {
System.out.println("criteria is "+(criteria ==null ? "null":" not null"));
List<Revision> revisions = persistence.getRevisions(criteria);
return revisions;
}
}
Criteria.java
#XmlRootElement
public class Criteria implements Serializable {
private static final long serialVersionUID = 1L;
public static final String LIST_TYPE = "criteria.key.listtype";
public static final String TYPE_ALL = "criteria.value.all";
public static final String TYPE_ERROR = "criteria.value.error";
public static final String TYPE_ARCHIVE = "criteria.value.archive";
public static final String TYPE_APPROVAL = "criteria.value.approval";
private Map<String, String> parameters;
public Map<String, String> getParameters() {
return parameters;
}
public String getParameter(String key) {
if (parameters==null || key==null) {
return null;
} else {
return parameters.get(key);
}
}
public void setParameters(Map<String, String> parameters) {
this.parameters = parameters;
}
public void setParameter(String key, String value) {
if (parameters==null) {
parameters = new HashMap<String,String>();
}
parameters.put(key, value);
}
public void setType(String type) {
setParameter(LIST_TYPE, type);
}
public String getType() {
return getParameter(LIST_TYPE);
}
#Override
public int hashCode() {
int hash = 7;
hash = 43 * hash + (this.parameters != null ? this.parameters.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Criteria other = (Criteria) obj;
if (this.parameters != other.parameters && (this.parameters == null || !this.parameters.equals(other.parameters))) {
return false;
}
return true;
}
}
Is there anything I'm missing like annotation or something?
Message sent looked like this:
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body><ns2:listRevisions xmlns:ns2="http://webservice.ecl.abc.com/"><ns2:criteria>
<type>TYPE_ALL</type></ns2:criteria></ns2:listRevisions></S:Body></S:Envelope>
HTTP/1.1 200 OK
server: grizzly/1.9.50
Content-Type: text/xml;charset=utf-8
Transfer-Encoding: chunked
Date: Fri, 17 May 2013 07:37:15 GMT
<?xml version='1.0' encoding='UTF-8'?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body>
<ns2:listRevisionsResponse xmlns:ns2="http://webservice.ecl.abc.com/"/></S:Body>
</S:Envelope>
Try adding targetNamespace to WebParam annotation, with the namespace of the schema.
I faced the same issue. The root element was defaulted to the service namespace instead of schema namespace. I added targetNamespace to WebParam and that helped resolve this issue.
#WebResult(name="status")
public String send(#WebParam(name="event",targetNamespace="http://efw/event/schema") EventType event);
getParameter/setParameter methods does not follow JavaBean convension. If you don't want not follow this convension use #XmlAccessorType(XmlAccessType.FIELD) at the class level - JAXB would look at fields, not methods.
getParameter/setParameters work with Map type, it can be done, but with some additional work (JAXB java.util.Map binding)
getType/setType are the only "proper" methods pair, so they are properly treated by JAXB
I can't comment yet (too low reputation) but I resolved this problem. My solution was to change the name of the #WebParam so that it has not the name of the Class:
public List<Revision> listRevisions(#WebParam(name="crit")Criteria criteria) {
instead of
public List<Revision> listRevisions(#WebParam(name="criteria")Criteria criteria) {
I don't know why it happens though. Maybe someone can give an insight.

Resources