i try to passing numeric parameter to a web service that receive the value and return it back.
this is the snippet of the web method :
#WebMethod(operationName = "getNumber")
public Integer getNumber(#WebParam(name = "i")
Integer i) {
//TODO write your implementation code here:
System.out.println("number : "+i);
return i;
}
an this is the snippet of my client code :
Map results = FastMap.newInstance();
results.put("result", "success");
String endPoint = "http://localhost:8084/ProvideWS/MathWS";
URL endpoint=null;
try{
endpoint = new URL(endPoint);
}
catch (MalformedURLException e) {
org.ofbiz.base.util.Debug.log("Location not a valid URL "+e);
// TODO: handle exception
}
Service service = null;
Call call = null;
try{
service = new Service();
call = (Call)service.createCall();
call.setTargetEndpointAddress(endpoint);
String nameSpace = "http://ws/";
String serviceName = "getNumber";
call.setOperationName(new QName(nameSpace, serviceName));
call.addParameter("i",org.apache.axis.Constants.XSD_INTEGER , ParameterMode.IN);
call.setReturnType(org.apache.axis.Constants.XSD_INTEGER);
Object msg[] = new Object[]{new Integer(5)};
for (Object o : msg) {
org.ofbiz.base.util.Debug.log("object to be sent===== "+o.toString());
}
Object ret = call.invoke(msg);
results.put("result", "result : "+ ret.toString());
}
catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
org.ofbiz.base.util.Debug.log("exc when running soap client test : "+e);
results.put("result", "error : "+e);
}
return results;
the problem is the return value in the client always 0 (the server received the number as zero), the method i used to pass the parameter works fine when the paramater is String. I.ve tried to hard-coding the return value in server and the output in client is fine, so i thought it must be how the server retrieved the parameter is the problem.
do you have any idea why this is happen and how to solve this?
any help will be appreciated, thanks
I don't know what is causing your problem. But the first thing I would do would be to try to capture the actual request that is being sent to the server. That should give you some clues as to whether the root problem is on the client or server side.
Related
anyone tried to connect to Marklogic using XCC java classes - I want to connect and do a query but not use an 'adhocquery' (xquery) - is this possible? Using the XCC Session or Request classes?
Instead of executing an adhocQuery, you could invoke a module using request.newModuleInvoke()
String connectionUri = "xcc://user:password#localhost:8888";
String moduleUri = "/some/module.xqy";
ContentSource contentSource = ContentSourceFactory.newContentSource(connectionUri);
ResultSequence resultSequence = null;
try (Session session = contentSource.newSession()) {
Request request = session.newModuleInvoke(moduleUri);
/*
*if you need to set request parameters, look at the setXXXVariable methods
* https://docs.marklogic.com/javadoc/xcc/com/marklogic/xcc/Request.html
* i.e.
* request.setNewStringVariable("foo", "bar");
* request.setVariable(xdmVariable); //see also: ValueFactory.newVariable()
*/
resultSequence = session.submitRequest(request);
//do stuff with the result sequence
} catch (RequestException exc) {
//Determine if the exception is retryable or should fail
} catch (Exception exc) {
//Determine what to do with other exceptions
} finally {
//unfortunately, ResultSequence doesn't implement closable...
if (null != resultSequence && !resultSequence.isClosed()) {
resultSequence.close();
resultSequence = null;
}
}
When trying to use a webservice, a NullPointerException is thrown, and expected log statements are missing in the application's log.
I get a NullPointerException in the following code:
public void useWebservice() {
initEndpoint();
try {
port.usefulFunctionWebserviceProvides(); // NullPointerException is thrown here!
} catch (javax.xml.ws.soap.SOAPFaultException ex) {
log.error("Something went wrong making a request to the webservice");
}
}
The initEndpoint method looks like this:
private volatile Webservice service = null; // instance variable
private WebservicePort port = null; // instance variable
private void initEndpoint() {
String username = "username"; // Loaded from a properties file
String password = "password"; // Loaded from a properties file
LoginResponse loginResponse;
Webservice theService = service;
if (theService == null || port == null) {
synchronized (this) {
theService = service;
if (theService == null) {
try {
log.info("Initializing Endpoint (service & port)"); // This line appears in the log
service = new Webservice();
port = service.getWebservicePort();
final String wsdlUrl = properties.getProperty(WSDL_URL, WSDL_DEFAULT_URL);
((BindingProvider)port).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, wsdlUrl);
log.info("EndpointAddress set");
LoginRequestType loginRequest = new LoginRequestType();
loginRequest.setUsername(username);
loginRequest.setPassword(password);
loginResponse = port.login(loginRequest, null, null);
} catch (Exception e) {
try {
log.info("re-Initializing Endpoint (service & port)");
// Try to connect to the webservice using a fallback URL
} catch (Exception e2) {
log.error("Couldn't connect to webservice");
service = null;
throw new CustomException();
}
}
if (loginResponse == null) {
service = null;
throw new CustomException();
}
}
}
}
}
None of the info logging is printed to the log file except for the log message "Initializing Endpoint (service & port)".
I don't understand how the port variable can be null in the useWebservice method. I also expect to see either "EndpointAddress set" or "re-Initializing Endpoint (service & port)" in the log file. But neither are printed to the file.
The code has worked fine before, but has started to give problems after being moved to a new project and used as a dependency.
The problem has been identified, it was a missing dependency. Because of that an error was thrown when the code tried to initialize the port. The catch block only catches exceptions so that code was never executed. If we caught throwable for example we would see the log statements from the catch block.
PS: Initializing the port object as it is done in the initEndpoint method in the question is NOT thread safe! The port needs to be initialized for each request.
I am trying to test if the server will return the string. However, I want to test it without actually connecting to the server. I am trying to get rid of the java.net.SocketException by mocking the server. What approach should I do?
The code below declares all of the necessary values for the server.
#RunWith(MockitoJUnitRunner.class)
public class testTransfer {
#Test
public void getServerMessage() {
//variables
String serverhostname = "serverA";
int portNo = 8888;
int versionNo = 9999;
String protocol = "tcp";
String serverInput = "input string";
String url = "http://localhost:8080/server/url";
Service service =new Service();
Call call = Mockito.mock(Call.class);
server_string result = Mockito.mock(server_string.class);
The code below calls the server and adds values inside the xml.
//try catch
try {
call=(Call)service.createCall();
QName qn = new QName("urn:ServerApiService", "server_string" );
call.registerTypeMapping(server_string.class, qn,
new org.apache.axis.encoding.ser.BeanSerializerFactory(server_string.class, qn),
new org.apache.axis.encoding.ser.BeanDeserializerFactory(server_string.class, qn));
call.setTargetEndpointAddress( new java.net.URL(url) );
call.addParameter("arg1", XMLType.XSD_STRING, ParameterMode.IN);
call.addParameter("arg2", XMLType.XSD_INT, ParameterMode.IN);
call.addParameter("arg3", XMLType.XSD_INT, ParameterMode.IN);
call.addParameter("arg4", XMLType.XSD_STRING, ParameterMode.IN);
call.addParameter("arg5", XMLType.XSD_STRING, ParameterMode.IN);
call.addParameter("arg6", qn, ParameterMode.OUT);
call.setOperationName( new QName(url, "getServerMessage") );
call.setReturnClass(server_string.class);
//result = (server_string) call.invoke( new Object[] {serverhostname,portNo,versionNo,protocol,serverInput} );
result = (server_string) Mockito.when(call.invoke( new Object[] {serverhostname,portNo,versionNo,protocol,serverInput} )).thenReturn(server_string.class);
System.out.println("Get server_string object from server ....");
// System.out.println("Value is "+result.value);
} catch (ServiceException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
However, I keep getting this
AxisFault
faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.userException
faultSubcode:
faultString: java.net.SocketException: Connection reset
faultActor:
faultNode:
faultDetail:
{http://xml.apache.org/axis/}stackTrace:java.net.SocketException: Connection reset
I have used wiremock to good effect. It's a mocking framework specifically for this job.
You may also use JBoss and run the project. When mocking the server you need to use what #Bohemian said because it is much easier that way. However, the learning curve is high and is not recommended for emergency situations(i'm a newbie btw).
I am trying to write an RPC with Thrift, the client seems to be communicating to the server just fine, and the server creates a list to return to the client (proper format). But then the client somehow cannot recognize the packet as I get this error:
org.apache.thrift.TApplicationException: getEntityByIP failed: unknown result
This is what my thrift file looks like:
struct EntityLookupMessage{
1: list<i32> entityIDs;
}
service EntityJoinService {
list<i32> getEntityByIP(1:string IPval,2:i32 date);
}
And the ServerImpl is the following method:
public List<Integer> getEntityByIP(String IPval, int date) throws TException {
try{
System.out.println("Checking..."+IPval);
List<Integer> response=EntityJoinStandalone.getEntityByIP(entityLookup,IPval, date);
System.out.println(response);
return response;
}finally{
// TODO Auto-generated method stub
return null
}
Which is called by a client like so:
List<Integer> entity = client.getEntityByIP(IPval, date);
Any ideas why this is the case?
Cause
Thrift by design doesn't allow for null results. This is the code of the generated recv_Xxx() function:
public List<Integer> recv_getEntityByIP() throws org.apache.thrift.TException
{
getEntityByIP_result result = new getEntityByIP_result();
receiveBase(result, "getEntityByIP");
if (result.isSetSuccess()) {
return result.success;
}
throw new org.apache.thrift.TApplicationException(
org.apache.thrift.TApplicationException.MISSING_RESULT,
"getEntityByIP failed: unknown result");
}
You have to return a valid result, which is ...
a valid list, which may be empty, but must not be null
an exception thrown on the server
Solution
Remove the return null from your finally clause.
Best practice
Put the result into an object, similar to what you already did with the args:
struct EntityByIP_result {
1: list<i32> data;
}
This way you also leave room for further improvements down the road, you can add new fields to the struct at any time.
I am getting the below exception before hitting a axis 2 webservice.
org.apache.axis2.AxisFault: org.apache.axis2.databinding.ADBException: Unexpected subelement underTimelyRenewal
I can't reproduce the same issue locally on tomcat or in DEV environment which runs in Weblogic. It justs happens only in 1 environment which runs on Weblogic 11g. This makes to think that I am missing some config in that environment, I am not sure what it is. Any help on this is highly appreciated.
Here is code that calls web service.
public com.ibs.accouting.employeeVerificationResponse getEmployeeVerificationRequest(
com.ibs.accounting.EmployeeVerificationRequest employeeVerificationRequest108)
throws java.rmi.RemoteException
{
org.apache.axis2.context.MessageContext _messageContext = null;
try{
org.apache.axis2.client.OperationClient _operationClient = _serviceClient.createClient(_operations[5].getName());
_operationClient.getOptions().setAction("http://ibs.com/accounting/WBLEmployeeVerificationRequest");
_operationClient.getOptions().setExceptionToBeThrownOnSOAPFault(true);
addPropertyToOperationClient(_operationClient,org.apache.axis2.description.WSDL2Constants.ATTR_WHTTP_QUERY_PARAMETER_SEPARATOR,"&");
// create a message context
_messageContext = new org.apache.axis2.context.MessageContext();
// create SOAP envelope with that payload
org.apache.axiom.soap.SOAPEnvelope env = null;
env = toEnvelope(getFactory(_operationClient.getOptions().getSoapVersionURI()),
employeeVerificationRequest108,
optimizeContent(new javax.xml.namespace.QName("http://ibs.com/accounting",
"getEmployeeVerificationRequest")));
//adding SOAP soap_headers
_serviceClient.addHeadersToEnvelope(env);
// set the message context with that soap envelope
_messageContext.setEnvelope(env);
// add the message contxt to the operation client
_operationClient.addMessageContext(_messageContext);
//execute the operation client
_operationClient.execute(true);
org.apache.axis2.context.MessageContext _returnMessageContext = _operationClient.getMessageContext(
org.apache.axis2.wsdl.WSDLConstants.MESSAGE_LABEL_IN_VALUE);
org.apache.axiom.soap.SOAPEnvelope _returnEnv = _returnMessageContext.getEnvelope();
java.lang.Object object = fromOM(
_returnEnv.getBody().getFirstElement() ,
com.ibs.accounting.EmployeeVerificationResponse.class,
getEnvelopeNamespaces(_returnEnv));
return (com.ibs.accounting.EmployeeVerificationResponse)object;
}catch(org.apache.axis2.AxisFault f){
org.apache.axiom.om.OMElement faultElt = f.getDetail();
if (faultElt!=null){
if (faultExceptionNameMap.containsKey(faultElt.getQName())){
//make the fault by reflection
try{
java.lang.String exceptionClassName = (java.lang.String)faultExceptionClassNameMap.get(faultElt.getQName());
java.lang.Class exceptionClass = java.lang.Class.forName(exceptionClassName);
java.lang.Exception ex=
(java.lang.Exception) exceptionClass.newInstance();
//message class
java.lang.String messageClassName = (java.lang.String)faultMessageMap.get(faultElt.getQName());
java.lang.Class messageClass = java.lang.Class.forName(messageClassName);
java.lang.Object messageObject = fromOM(faultElt,messageClass,null);
java.lang.reflect.Method m = exceptionClass.getMethod("setFaultMessage",
new java.lang.Class[]{messageClass});
m.invoke(ex,new java.lang.Object[]{messageObject});
throw new java.rmi.RemoteException(ex.getMessage(), ex);
}catch(java.lang.ClassCastException e){
// we cannot intantiate the class - throw the original Axis fault
throw f;
} catch (java.lang.ClassNotFoundException e) {
// we cannot intantiate the class - throw the original Axis fault
throw f;
}catch (java.lang.NoSuchMethodException e) {
// we cannot intantiate the class - throw the original Axis fault
throw f;
} catch (java.lang.reflect.InvocationTargetException e) {
// we cannot intantiate the class - throw the original Axis fault
throw f;
} catch (java.lang.IllegalAccessException e) {
// we cannot intantiate the class - throw the original Axis fault
throw f;
} catch (java.lang.InstantiationException e) {
// we cannot intantiate the class - throw the original Axis fault
throw f;
}
}else{
throw f;
}
}else{
throw f;
}
} finally {
_messageContext.getTransportOut().getSender().cleanup(_messageContext);
}
}
This error can be kind of misleading. AFter I modified the WSDL and added a new mandatory element, I created my client. Than this error appeared. The solution was, that I forgot to fill this element in one method of the my web service. If this error appears, also check if your mandatory elements are filled within the server.
That it works under one environment and not in an other can also mean, that a mandatory item is filled on one server (development server) and not under the other (productive server).