Problems parsing webservice response (Metro/JAXB) - java

I have generated a Metro/JAXB client from a WSDL before and the marshalling/unmarshalling of the Java classes to/from SOAP/XML worked without any issues. I have generated a new client and there seems to be unmarshalling issues and I'm not sure why. The WSDL is very large (> 27,000 lines) and I had to use -B-XautoNameResolution because of some element names being the same except for case.
I am trying to execute this method/operation:
#WebService(name = "servicePortType", targetNamespace = "urn:service")
#XmlSeeAlso({
ObjectFactory.class
})
public interface ServicePortType {
/**
* Service definition of function unsp__GetSubscriberList
*
* #param result
* #param totalSubsFound
* #param getSubListReq
* #param paginatedInfo
* #param getSubscriberListData
*/
#WebMethod(operationName = "GetSubscriberList")
#RequestWrapper(localName = "GetSubscriberList", targetNamespace = "urn:service", className = "service.GetSubscriberList")
#ResponseWrapper(localName = "GetSubscriberListResult", targetNamespace = "urn:service", className = "service.GetSubscriberListResult")
public void getSubscriberList(
#WebParam(name = "GetSubListReq", targetNamespace = "")
GetSubscriberListRequest getSubListReq,
#WebParam(name = "Result", targetNamespace = "", mode = WebParam.Mode.OUT)
Holder<ResultCodeStruct> result,
#WebParam(name = "PaginatedInfo", targetNamespace = "", mode = WebParam.Mode.OUT)
Holder<PaginatedInfo> paginatedInfo,
#WebParam(name = "TotalSubsFound", targetNamespace = "", mode = WebParam.Mode.OUT)
Holder<Integer> totalSubsFound,
#WebParam(name = "GetSubscriberListData", targetNamespace = "", mode = WebParam.Mode.OUT)
Holder<GetSubscriberListData> getSubscriberListData);
}
This method will return the subscriber data and also the total number of subscribers. My call looks like this:
public int getTotalSubscriptions()
throws Exception
{
GetSubscriberListRequest subscriberListRequest = factory.createGetSubscriberListRequest();
Holder<ResultCodeStruct> result = null;
Holder<PaginatedInfo> paginatedInfo = null;
Holder<Integer> totalSubsFound = null;
Holder<GetSubscriberListData> subscriberListData = null;
subscriberListRequest.setMaxSubscribers(factory.createGetSubscriberListRequestMaxSubscribers(1));
port.getSubscriberList(subscriberListRequest,
result,
paginatedInfo,
totalSubsFound,
subscriberListData);
if (result.value.getResultCode() != CODE_SUCCESS)
{
throw new Exception("Failed call");
}
return totalSubsFound.value.intValue();
}
I get a NullPointerException on the result object. I have traced the SOAP call and the XML being returned is as expected including a Result element.
I have never encountered WebParam.Mode.OUT before. Should the Holder<> instances be initialized before I make the call? To what?
Those elements are wrapped in a GetSubscriberListResult element in the SOAP, but since the interface method has that defined in the #ResponseWrapper, I was expecting them to be unmarshalled into the objects passed in. Maybe I need to do something else?
Any advice/help is greatly appreciated!

Spent quite a bit of time searching on the internet and found an older reference stating that the Holder objects do need to be initialized. So, the corrected method calls looks like this:
public int getTotalSubscriptions()
throws Exception
{
GetSubscriberListRequest subscriberListRequest = factory.createGetSubscriberListRequest();
Holder<ResultCodeStruct> result = new Holder<ResultCodeStruct>(factory.createResultCodeStruct());
Holder<PaginatedInfo> paginatedInfo = new Holder<PaginatedInfo>(factory.createPaginatedInfo());
Holder<Integer> totalSubsFound = new Holder<Integer>(new Integer(0));
Holder<GetSubscriberListData> subscriberListData = new Holder<GetSubscriberListData>(factory.createGetSubscriberListData());
subscriberListRequest.setMaxSubscribers(factory.createGetSubscriberListRequestMaxSubscribers(1));
port.getSubscriberList(subscriberListRequest,
result,
paginatedInfo,
totalSubsFound,
subscriberListData);
if (result.value.getResultCode() != CODE_SUCCESS)
{
throw new Exception("Failed call");
}
return totalSubsFound.value.intValue();
}
Hope this helps others who may have encountered the same issue.

Related

WSDL Client from Intellij generated code

I am trying to make a client connect to a web service and use a SetFlight method on the server.
The environment is Intellij Ultimate, Java 7, and JAXWS. The generation of the classes from the WSDL has been done.
Among the generated classes I have two services:
#WebServiceClient(name = "FOService", targetNamespace = "http://temporaryuri.org.au/", wsdlLocation = "http://fovanil.com/FOService.svc?wsdl")
public class FOService
extends Service
{
private final static URL FOSERVICE_WSDL_LOCATION;
private final static WebServiceException FOSERVICE_EXCEPTION;
private final static QName FOSERVICE_QNAME = new QName("http://temporaryuri.org.au/", "FOService");
static {
...
And the IFO service
#WebService(name = "IFOService", targetNamespace = "urn:fo.com.au/schema/common")
#SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
#XmlSeeAlso({
ObjectFactory.class
})
public interface IFOService {
/**
*
* #param parameters
* #return
* returns svc.SetFlightResponse
*/
#WebMethod(operationName = "SetFlight", action = "http://fo.com.au/SetFlight")
#WebResult(name = "SetFlightResponse", targetNamespace = "urn:fo.com.au/schema/common/types", partName = "parameters")
public SetFlightResponse SetFlight(
#WebParam(name = "SetFlightRequest", targetNamespace = "urn:fo.com.au/schema/common/types", partName = "parameters")
SetFlightRequest parameters);
}
I have looked at some examples of implementing a client https://docs.oracle.com/javaee/5/tutorial/doc/bnayn.html however this differs.
I would have thought using this would be:
IFOSerice service = new IFOService();
service.SetFlight(someinstanceofflight); //setFlight is not a available method
How do I make a client and use the SetFlight method?
This code worked:
SetFORequest request = new SetFORequest();
SetFOResponse response = new SetFOResponse();
request.setFO(flight);
FOService foService = new FOService();
IfoService ifoService = foService.getWSHttpBindingIFOService();
ifoService.setFO(request);

Soap Request using axis2 java in Eclipse

I want to make an insert operation in an import set table through the web service from ServiceNow with axis2 version 1.6.4
I used wsdl2java with the wsdl file to create classes in my java project.
After it, i created a new class Request on which i would build my soap request to the webservice.
I believe I have 2 (might be more) major problems:
Unserstanding the difference between a stub and a proxy, respectively, the classes ServiceNowSoapStub and ServiceNowSoapProxy and what is the purpose of each of them.
The existing insert method needs a lot of arguments and i wish to make inserts with a selected number of arguments. do i need to add that specific insert method to the architecture?
Here is what I have:
public class Request {
public static void main(String[] args) throws RemoteException {
try{
HttpTransportProperties.Authenticator basicAuthentication = new HttpTransportProperties.Authenticator();
basicAuthentication.setUsername("xxxx");
basicAuthentication.setPassword("xxxx");
ServiceNowSoapStub proxy = new ServiceNowSoapStub();
proxy._setProperty(org.apache.axis2.transport.http.HTTPConstants.CHUNKED, Boolean.FALSE);
proxy._setProperty(org.apache.axis2.transport.http.HTTPConstants.AUTHENTICATE, basicAuthentication);
BigDecimal actuals = new BigDecimal("0.04");
BigInteger appId = new BigInteger("3495766");
String appNonApp = "ApNon";
BigInteger productId = new BigInteger("704217");
BigInteger serviceId = new BigInteger("1537");
String serviceName = "IT";
String bpName = "BNK-RSK";
String method = "N";
String bsCode = "ITDV";
String customerCostCode = "30973250";
String customerCountry = "US";
String customerGroup = "Wealth";
String customerLegalEntity = "HB";
String dsId = "EU56";
BigInteger supplierCostCode = new BigInteger("675136");
String supplierCountry = "UK";
String supplierLegalEntity = "BR";
BigInteger total = new BigInteger ("411");
ServiceNowSoapProxy request = new ServiceNowSoapProxy("https://dev34363.service-now.com/u_it_actuals_import_set");
request.insertTest(actuals, appId, appNonApp, productId, serviceId, serviceName, bpName, method, bsCode, customerCostCode,
customerCountry, customerGroup, customerLegalEntity, dsId, supplierCostCode, supplierCountry, supplierLegalEntity, total);
} catch (org.apache.axis.AxisFault e) {
e.printStackTrace();
}
}
}
What am I doing wrong? or can please anyone refer me to some helpful link?
The wiki page of servicenow addressing this subject is a bit out of date so i can't solve my problem through it.
Thanks!

How to use termVector in solrJ

Solr/SolrJ Version: 6.0.0
I've set termvector component in solrconfig.xml, and the request handler is "/tvrh", I test it in the browser and this works. Now I want to use it in solrJ, but it only returns the document. The following is my code:
SolrClient solrClient = new HttpSolrClient("http://localhost:8983/solr/test");
SolrQuery solrQuery = new SolrQuery();
solrQuery.setQuery(String.format("id:%s","clueweb12-0000tw-06-17744"));
solrQuery.setRequestHandler("/tvrh");
solrQuery.set("tv", true);
solrQuery.set("tv.all", true);
QueryResponse response = solrClient.query(solrQuery);
SolrDocumentList docs = response.getResults();
for (SolrDocument doc: docs){
for (String key: doc.keySet()){
System.out.println(key);
System.out.println(doc.getFieldValue(key));
}
}
Your question is how to use a non standard request handler in solr.
Be aware that the Term Vector Component belongs to a "non standard" request handler and is not supported from solrj:
https://cwiki.apache.org/confluence/display/solr/The+Term+Vector+Component#TheTermVectorComponent-SolrJandtheTermVectorComponent
You can call "/tvrh" via solrj in a generic mode. You can not use the method SolrClient#query(SolrParams params) for this, because in this case the "request handler" is only send as "qt"-Parameter and will not be part of the url-path (and qt-Parameter is ignored by default).
So please try the method "SolrClient#request" instead.
As #Karsten R says, we could not use SolrClient.query to send request. After I searched a lot and experimented a lot, the following code could work.
SolrClient solrClient = new HttpSolrClient("http://localhost:8983/solr/trecB13");
SolrQuery solrQuery = new SolrQuery();
solrQuery.setQuery(String.format("id:%s","clueweb12-0000tw-06-17744"));
solrQuery.setRequestHandler("/tvrh");
solrQuery.set("tv", true);
solrQuery.set("tv.all", true);
try {
NamedList<Object> response = solrClient.request(new QueryRequest(solrQuery));
TermVectorExtractor extractor = new TermVectorExtractor(response);
System.out.println(extractor.getTermVectorInfo());
} catch (Exception e) {
e.printStackTrace();
}
TermVectorExtractor.java reference Sakai-Solr Github code, the function of the class is to parse resonse object and get term info. A little different from original code. The different has been shown below.
import org.apache.solr.common.util.NamedList;
import java.util.*;
public class TermVectorExtractor {
private static final String TERM_VECTORS = "termVectors";
private Map<String, Map<String, Map<String, TermInfo>>> termVectorInfo = Collections.emptyMap();
/**
* Creates a TermVectorExtractor for the given query response sent by Solr.
*
* #param queryResponse response sent by the solr server for a search query.
*/
#SuppressWarnings("unchecked")
public TermVectorExtractor(NamedList<Object> queryResponse) {
NamedList<Object> res = (NamedList<Object>) queryResponse.get(TERM_VECTORS);
if (res != null)
termVectorInfo = extractTermVectorInfo(res);
}
}

cast StringArray to String[] inside SOAP client

i have a service of SOAP webservice that return ArrayList<String[]>. When i call it from client, eclipse says me that service don't return ArrayList<String[]> but List<StringArray>.
StringArray don't seems to be a java data type, and i would know how i can convert it to String[] and extract data from it.
this is client imported file contains method for retrieve data:
#WebService(name = "Functions", targetNamespace = "http://example.com/")
#XmlSeeAlso({
ObjectFactory.class
})
public interface Functions {
/**
*
* #return
* returns java.util.List<com.example.StringArray>
*/
#WebMethod
#WebResult(targetNamespace = "")
#RequestWrapper(localName = "getData", targetNamespace = "http://example.com/", className = "com.example.GetData")
#ResponseWrapper(localName = "getDataResponse", targetNamespace = "http://example.com/", className = "com.example.GetDataResponse")
#Action(input = "http://example.com/Functions/getDataRequest", output = "http://example.com/Functions/getDataResponse")
public List<String[]> getData();
this is how this function is declared on server:
#WebMethod
public ArrayList<String[]> getData() {
// invoked by android app
dataStore = DatastoreServiceFactory.getDatastoreService();
ArrayList<Entity> list = (ArrayList<Entity>) dataStore.prepare(query).asList(FetchOptions.Builder.withLimit(100));
if (!list.isEmpty()) {
ArrayList<String[]> res=new ArrayList<String[]>();
String[] to_add;
// convert entity into strings
for (Entity current : list) {
to_add=new String[3];
to_add[0]=String.valueOf(current.getProperty(TEMP_ROW));
to_add[1]=String.valueOf(current.getProperty(HUM_ROW));
to_add[2]=String.valueOf(current.getProperty(DATE_ROW));
res.add(to_add);
}
return res;
}
return null;
}
You can use the toArray() method from the Collection
List<String> myList = myClient.getData();
String[] myArray = myList.toArray();

wsimport not using complex input types

When I use wsimport to generate proxies for some services, the resulting method signature for each port does not seem to use the complex types specified in the WSDL; but yet I've noticed that with some other services it does.
This has happened on multiple services, but the most recent example is Amazon's AWSEConsumerService (link to WSDL). When I generate the service proxy code using wsimport, I get method signatures such as the following for each port.
#WebMethod(operationName = "ItemLookup", action = "http://soap.amazon.com/ItemLookup")
#RequestWrapper(localName = "ItemLookup", targetNamespace = "http://webservices.amazon.com/AWSECommerceService/2011-08-01", className = "com.aws.CommerceService.ItemLookup")
#ResponseWrapper(localName = "ItemLookupResponse", targetNamespace = "http://webservices.amazon.com/AWSECommerceService/2011-08-01", className = "com.aws.CommerceService.ItemLookupResponse")
public void itemLookup(
#WebParam(name = "MarketplaceDomain", targetNamespace = "http://webservices.amazon.com/AWSECommerceService/2011-08-01")
String marketplaceDomain,
#WebParam(name = "AWSAccessKeyId", targetNamespace = "http://webservices.amazon.com/AWSECommerceService/2011-08-01")
String awsAccessKeyId,
#WebParam(name = "AssociateTag", targetNamespace = "http://webservices.amazon.com/AWSECommerceService/2011-08-01")
String associateTag,
#WebParam(name = "Validate", targetNamespace = "http://webservices.amazon.com/AWSECommerceService/2011-08-01")
String validate,
#WebParam(name = "XMLEscaping", targetNamespace = "http://webservices.amazon.com/AWSECommerceService/2011-08-01")
String xmlEscaping,
#WebParam(name = "Shared", targetNamespace = "http://webservices.amazon.com/AWSECommerceService/2011-08-01")
ItemLookupRequest shared,
#WebParam(name = "Request", targetNamespace = "http://webservices.amazon.com/AWSECommerceService/2011-08-01")
List<ItemLookupRequest> request,
#WebParam(name = "OperationRequest", targetNamespace = "http://webservices.amazon.com/AWSECommerceService/2011-08-01", mode = WebParam.Mode.OUT)
Holder<OperationRequest> operationRequest,
#WebParam(name = "Items", targetNamespace = "http://webservices.amazon.com/AWSECommerceService/2011-08-01", mode = WebParam.Mode.OUT)
Holder<List<Items>> items);
I would expect this method take the single complex parameter specified by the WSDL (in this case an ItemLookup object). Am I fundamentally misunderstanding something or is there something abnormal happening with the code generation?
I ran into a similar problem with AWS. I followed the API setup description for Java (page 10 of this pdf
In step 2 (it says for Eclipse 3.2) you should create a file (sugessted name is jaxws-custom.xml) with the following content:
<jaxws:bindings wsdlLocation="http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl" xmlns:jaxws="http://java.sun.com/xml/ns/jaxws">
<jaxws:enableWrapperStyle>false</jaxws:enableWrapperStyle>
</jaxws:bindings>
and then run the wsimport command with the option -b jaxws-custom.xml
I haven't figured out what exactly the problem is, but that did the trick for me.

Categories