Java - Override a WebRequest on Web Service Call - java
Quick background, our company connects to an ERP system (Sage) via web services for some functions. We have both c# (.net) and java code that performs calls to the Web Service (WS). Recently Sage introduced Basic Authentication into their WS.
Please note: This is a JAVA question, but I'll show an example in C# first to explain.
In the c# program, I first would create an object that is for accessing the WS:
var sageService = new CAdxWebServiceXmlCCServiceBasicAuth();
I then set up credential information:
var sageServiceCallContext = SageFactory.Instance.GetCallContext();
sageService.Credentials = new NetworkCredential(SageUser, SagePwd);
sageService.PreAuthenticate = true;
then finally the call to the specific web service method:
sageCustomerSvcResponse = sageService.run(sageServiceCallContext, "YTDPROF", sageCustomerRequestInXml);
When I set up the service object I use a custom class that looks like this:
public class CAdxWebServiceXmlCCServiceBasicAuth : CAdxWebServiceXmlCCService
{
protected override WebRequest GetWebRequest(Uri uri)
{
HttpWebRequest webRequest = (HttpWebRequest)base.GetWebRequest(uri);
NetworkCredential credentials = Credentials as NetworkCredential;
if (credentials != null)
{
string authInfo = "";
if (credentials.Domain != null && credentials.Domain.Length > 0)
{
authInfo = string.Format(#"{0}\{1}:{2}", credentials.Domain, credentials.UserName, credentials.Password);
}
else
{
authInfo = string.Format(#"{0}:{1}", credentials.UserName, credentials.Password);
};
authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
webRequest.Headers["Authorization"] = "Basic " + authInfo;
}
return webRequest;
}
}
What happens is that now, when I perform any call to the web service methods, the GetWebRequest from the class is invoked every time. This is how we implemented basis authentication in c#.
How do I do this in Java?
In the java code currently, I create the service object (that which accesses the web services) this way:
WebServiceInvoker service = new WebServiceInvoker(SageWSURL,"");
and the WebServiceInvoker looks like this (truncated for brevity):
public WebServiceInvoker(String url, String dummy) throws ServiceException, IOException {
serviceLocator = new CAdxWebServiceXmlCCServiceLocator();
service = serviceLocator.getCAdxWebServiceXmlCC(url);
cc = new CAdxCallContext();
cc.setCodeLang("ENG");
cc.setCodeUser("USER");
cc.setPassword("PAWWORD");
cc.setPoolAlias("POOL");
cc.setRequestConfig("adxwss.trace.on=on&adxwss.trace.size=16384&adonix.trace.on=on&adonix.trace.level=3&adonix.trace.size=8");
log = new PrintWriter(new BufferedWriter(new FileWriter("C:/Kalio/service/orders/log.txt")));
}
the webservice locator looks like this:
public class CAdxWebServiceXmlCCServiceLocator extends org.apache.axis.client.Service implements com.adonix.www.WSS.CAdxWebServiceXmlCCService {
public CAdxWebServiceXmlCCServiceLocator() {
}
public com.adonix.www.WSS.CAdxWebServiceXmlCC getCAdxWebServiceXmlCC() throws javax.xml.rpc.ServiceException {
java.net.URL endpoint;
System.out.println("using local Sage Web Servivce URL:" + CAdxWebServiceXmlCC_address);
try {
endpoint = new java.net.URL(CAdxWebServiceXmlCC_address);
}
catch (java.net.MalformedURLException e) {
throw new javax.xml.rpc.ServiceException(e);
}
return getCAdxWebServiceXmlCC(endpoint);
}
public com.adonix.www.WSS.CAdxWebServiceXmlCC getCAdxWebServiceXmlCC(java.net.URL portAddress) throws javax.xml.rpc.ServiceException {
try {
com.adonix.www.WSS.CAdxWebServiceXmlCCSoapBindingStub _stub = new com.adonix.www.WSS.CAdxWebServiceXmlCCSoapBindingStub(portAddress, this);
_stub.setPortName(getCAdxWebServiceXmlCCWSDDServiceName());
return _stub;
}
catch (org.apache.axis.AxisFault e) {
return null;
}
}
and the specific method within that class is this:
public String getCustomer(String constructedXML) throws RemoteException {
**CAdxResultXml result = service.run(cc, "XTDPROF", constructedXML);**
CAdxMessage[] messages = result.getMessages();
for (int i = 0; i<messages.length; i++) {
CAdxMessage message = messages[i];
log.println("X3 get customer message: " + message.getMessage());
log.println("X3 get customer message type: " + message.getType());
}
return result.getResultXml();
}
So my questions is, how to I emulate that override that I see in the .net program in Java? It seems like it would be somewhere in either the service locator or invoker, but the program does not use standard http classes, but this adxwss stuff. I tried a straight c# to java conversion and that way didn't help. I have seen examples where basicAuth is implemented, but not against web service calls.
The c# is pretty clear cut, because once I create the service object using the basicAuth override, every web service calls goes through the orderride. How does that happen in Java?
I'll be happy to provide more info if needed and I'll continue to look/experiment, but at the moment I'm treading water.
Adding:
In tracing through the java code I found the specific web service call (run) where an apache "call" object is created. Is this where basicauth can be added?
public com.adonix.www.WSS.CAdxResultXml run(com.adonix.www.WSS.CAdxCallContext callContext, java.lang.String publicName, java.lang.String inputXml) throws java.rmi.RemoteException {
if (super.cachedEndpoint == null) {
throw new org.apache.axis.NoEndPointException();
}
org.apache.axis.client.Call _call = createCall();
_call.setOperation(_operations[0]);
_call.setUseSOAPAction(true);
_call.setSOAPActionURI("");
_call.setSOAPVersion(org.apache.axis.soap.SOAPConstants.SOAP11_CONSTANTS);
_call.setOperationName(new javax.xml.namespace.QName("http://www.adonix.com/WSS", "run"));
setRequestHeaders(_call);
setAttachments(_call);
try { java.lang.Object _resp = _call.invoke(new java.lang.Object[] {callContext, publicName, inputXml});
if (_resp instanceof java.rmi.RemoteException) {
throw (java.rmi.RemoteException)_resp;
}
else {
extractAttachments(_call);
try {
return (com.adonix.www.WSS.CAdxResultXml) _resp;
} catch (java.lang.Exception _exception) {
return (com.adonix.www.WSS.CAdxResultXml) org.apache.axis.utils.JavaUtils.convert(_resp, com.adonix.www.WSS.CAdxResultXml.class);
}
}
} catch (org.apache.axis.AxisFault axisFaultException) {
throw axisFaultException;
}
}
The solution I came up with is not elegant, but then I'm not a guru in Java, just know enough to be given these tasks.
Our company uses Sage as our ERP system and Sage has a WSDL to define the basic web services it provides.
Sage Web Servicew WSDL
In their latest version of Sage they went with basic authentication, but did not build it into the new WSDL. Since I could not seem to extend the class (CAdxWebServiceXmlCCService), I just copied/pasted a new class called CAdxWebServiceXmlCCServiceBasicAuth. The full code is shown below if anyone ever has need to deal with something like this in a web service.
The key point where BaiscAuth set set up is in the getCAdxWebServiceXmlCC method. I added setPassword and setUserName to the stub that is returned. What this accomplishes is that every time I perform a webservice method call, that stub is now part of the header.
package com.adonix.www.WSS;
import java.net.URL;
import java.util.Base64;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import javax.xml.rpc.ServiceException;
public class CAdxWebServiceXmlCCServiceBasicAuth extends org.apache.axis.client.Service implements com.adonix.www.WSS.CAdxWebServiceXmlCCService {
public CAdxWebServiceXmlCCServiceBasicAuth() {
}
public CAdxWebServiceXmlCCServiceBasicAuth(org.apache.axis.EngineConfiguration config) {
super(config);
}
public CAdxWebServiceXmlCCServiceBasicAuth(java.lang.String wsdlLoc, javax.xml.namespace.QName sName) throws javax.xml.rpc.ServiceException {
super(wsdlLoc, sName);
}
// Use to get a proxy class for CAdxWebServiceXmlCC
private java.lang.String CAdxWebServiceXmlCC_address = "http://10.28.0.7:8124/soap-generic/syracuse/collaboration/syracuse/CAdxWebServiceXmlCC";
public java.lang.String getCAdxWebServiceXmlCCAddress() {
return CAdxWebServiceXmlCC_address;
}
// The WSDD service name defaults to the port name.
private java.lang.String CAdxWebServiceXmlCCWSDDServiceName = "CAdxWebServiceXmlCC";
public java.lang.String getCAdxWebServiceXmlCCWSDDServiceName() {
return CAdxWebServiceXmlCCWSDDServiceName;
}
public void setCAdxWebServiceXmlCCWSDDServiceName(java.lang.String name) {
CAdxWebServiceXmlCCWSDDServiceName = name;
}
public com.adonix.www.WSS.CAdxWebServiceXmlCC getCAdxWebServiceXmlCC(String userName,String password) throws javax.xml.rpc.ServiceException {
java.net.URL endpoint;
try {
endpoint = new java.net.URL(CAdxWebServiceXmlCC_address);
}
catch (java.net.MalformedURLException e) {
throw new javax.xml.rpc.ServiceException(e);
}
return getCAdxWebServiceXmlCC(endpoint,userName,password);
}
public com.adonix.www.WSS.CAdxWebServiceXmlCC getCAdxWebServiceXmlCC(java.net.URL portAddress,String userName,String password) throws javax.xml.rpc.ServiceException {
try {
com.adonix.www.WSS.CAdxWebServiceXmlCCSoapBindingStub _stub = new com.adonix.www.WSS.CAdxWebServiceXmlCCSoapBindingStub(portAddress, this);
_stub.setPortName(getCAdxWebServiceXmlCCWSDDServiceName());
_stub.setPassword(password);
_stub.setUsername(userName);
return _stub;
}
catch (org.apache.axis.AxisFault e) {
return null;
}
}
public void setCAdxWebServiceXmlCCEndpointAddress(java.lang.String address) {
CAdxWebServiceXmlCC_address = address;
}
/**
* For the given interface, get the stub implementation.
* If this service has no port for the given interface,
* then ServiceException is thrown.
*/
public java.rmi.Remote getPort(Class serviceEndpointInterface) throws javax.xml.rpc.ServiceException {
try {
if (com.adonix.www.WSS.CAdxWebServiceXmlCC.class.isAssignableFrom(serviceEndpointInterface)) {
com.adonix.www.WSS.CAdxWebServiceXmlCCSoapBindingStub _stub = new com.adonix.www.WSS.CAdxWebServiceXmlCCSoapBindingStub(new java.net.URL(CAdxWebServiceXmlCC_address), this);
_stub.setPortName(getCAdxWebServiceXmlCCWSDDServiceName());
return _stub;
}
}
catch (java.lang.Throwable t) {
throw new javax.xml.rpc.ServiceException(t);
}
throw new javax.xml.rpc.ServiceException("There is no stub implementation for the interface: " + (serviceEndpointInterface == null ? "null" : serviceEndpointInterface.getName()));
}
/**
* For the given interface, get the stub implementation.
* If this service has no port for the given interface,
* then ServiceException is thrown.
*/
public java.rmi.Remote getPort(javax.xml.namespace.QName portName, Class serviceEndpointInterface) throws javax.xml.rpc.ServiceException {
if (portName == null) {
return getPort(serviceEndpointInterface);
}
java.lang.String inputPortName = portName.getLocalPart();
if ("CAdxWebServiceXmlCC".equals(inputPortName)) {
return getCAdxWebServiceXmlCC();
}
else {
java.rmi.Remote _stub = getPort(serviceEndpointInterface);
((org.apache.axis.client.Stub) _stub).setPortName(portName);
return _stub;
}
}
public javax.xml.namespace.QName getServiceName() {
return new javax.xml.namespace.QName("http://www.adonix.com/WSS", "CAdxWebServiceXmlCCService");
}
private java.util.HashSet ports = null;
public java.util.Iterator getPorts() {
if (ports == null) {
ports = new java.util.HashSet();
ports.add(new javax.xml.namespace.QName("http://www.adonix.com/WSS", "CAdxWebServiceXmlCC"));
}
return ports.iterator();
}
/**
* Set the endpoint address for the specified port name.
*/
public void setEndpointAddress(java.lang.String portName, java.lang.String address) throws javax.xml.rpc.ServiceException {
if ("CAdxWebServiceXmlCC".equals(portName)) {
setCAdxWebServiceXmlCCEndpointAddress(address);
}
else
{ // Unknown Port Name
throw new javax.xml.rpc.ServiceException(" Cannot set Endpoint Address for Unknown Port" + portName);
}
}
/**
* Set the endpoint address for the specified port name.
*/
public void setEndpointAddress(javax.xml.namespace.QName portName, java.lang.String address) throws javax.xml.rpc.ServiceException {
setEndpointAddress(portName.getLocalPart(), address);
}
#Override
public CAdxWebServiceXmlCC getCAdxWebServiceXmlCC() throws ServiceException {
// TODO Auto-generated method stub
return null;
}
#Override
public CAdxWebServiceXmlCC getCAdxWebServiceXmlCC(URL portAddress) throws ServiceException {
// TODO Auto-generated method stub
return null;
}
}
Related
Method keeps running and sending the same information even for different request grpc
I am trying to implement GRPC and when i do so I get the correct response from the server and if I stop the server and run it again and use the other request that I implemented it works however if I try and make a second request straight after making one in from the first request I get the same response. It's like it is looping. These are the two methods I am using from the client: public void setSpaces(int id) { channel =ManagedChannelBuilder.forAddress("localhost", 3000) // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid // needing certificates. .usePlaintext() .build(); blockingStub = carParkServiceGrpc.newBlockingStub(channel); asyncStub = carParkServiceGrpc.newStub(channel); logger.info("Will try to get CarPark " + id + " ..."); CarParkToUpdateRequest request = CarParkToUpdateRequest.newBuilder().setDeviceId(id).build(); carParkResponse response; try { response = blockingStub.setSpaces(request); }catch(StatusRuntimeException e) { logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus()); return; }finally { channel.shutdown(); } logger.info("Carpark: " + response.getCarPark()); spacesArea.append(response.getCarPark().toString()); } public void setFull(int id) { channel =ManagedChannelBuilder.forAddress("localhost", 3000) // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid // needing certificates. .usePlaintext() .build(); blockingStub = carParkServiceGrpc.newBlockingStub(channel); asyncStub = carParkServiceGrpc.newStub(channel); logger.info("Will try to get CarPark " + id + " ..."); CarParkToUpdateRequest request = CarParkToUpdateRequest.newBuilder().setDeviceId(id).build(); carParkResponse response; try { response = blockingStub.setFull(request); }catch(StatusRuntimeException e) { logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus()); return; }finally { channel.shutdown(); } logger.info("Carpark: " + response.getCarPark()); fullArea.append(response.getCarPark().toString()); } These two methods are supposed to send a request to the server to change the status of the 'car park' so if I send a request with setFull I get a response saying the carpark is full etc. These are the methods from the server: public void setSpaces(CarParkToUpdateRequest request, StreamObserver<carParkResponse> rStreamObserver) { ArrayList<CarParkOperations.proto.cp.CarPark> carList = Car.getInstance(); for(int i=0; i<carList.size(); i++) { if(carList.get(i).getCarParkId() == request.getDeviceId()) { CarParkOperations.proto.cp.CarPark heater_rec = (CarParkOperations.proto.cp.CarPark) carList.get(i); Car.carparkCar.clear(); Car.carparkCar.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(heater_rec.getCarParkId()).setLocation(heater_rec.getLocation()).setStatus("Spaces").build()); } } for(CarParkOperations.proto.cp.CarPark heater : Car.carparkCar) { carParkResponse response = carParkResponse.newBuilder().setCarPark(heater).build(); rStreamObserver.onNext(response); rStreamObserver.onCompleted(); return; } } public void setFull(CarParkToUpdateRequest request, StreamObserver<carParkResponse> rStreamObserver) { ArrayList<CarParkOperations.proto.cp.CarPark> carList = Car.getInstance(); for(int i=0; i<carList.size(); i++) { if(carList.get(i).getCarParkId() == request.getDeviceId()) { CarParkOperations.proto.cp.CarPark heater_rec = (CarParkOperations.proto.cp.CarPark) carList.get(i); Car.carparkCar.clear(); Car.carparkCar.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(heater_rec.getCarParkId()).setLocation(heater_rec.getLocation()).setStatus("Full").build()); } } for(CarParkOperations.proto.cp.CarPark heater : Car.carparkCar) { carParkResponse response = carParkResponse.newBuilder().setCarPark(heater).build(); rStreamObserver.onNext(response); rStreamObserver.onCompleted(); return; } } I think it's most likely something to do with the server methods but cant seem to figure it out. This is where I am storing the data: package CarParkOperations.proto.cp; import java.util.ArrayList; import com.google.rpc.Status; public class Car extends ArrayList<CarPark>{ public static Car carparkCar; public static Car getInstance() { if(carparkCar == null) { carparkCar = new Car(); } return carparkCar; } public Car() { this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(1).setStatus("Full").setLocation("Behind Building 1").build()); this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(2).setStatus("Full").setLocation("Behind Building 1").build()); this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(3).setStatus("Full").setLocation("Behind Building 4").build()); this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(4).setStatus("Full").setLocation("Behind Building 3").build()); this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(5).setStatus("Full").setLocation("Behind Building 2").build()); this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(6).setStatus("Full").setLocation("Behind Building 1").build()); this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(7).setStatus("Full").setLocation("Behind Building 1").build()); this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(10).setStatus("Full").setLocation("Behind Building 6").build()); this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(11).setStatus("Full").setLocation("Behind Building 1").build()); this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(12).setStatus("Spaces").setLocation("Behind Building 1").build()); this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(13).setStatus("Spaces").setLocation("Behind Building 1").build()); this.add(CarParkOperations.proto.cp.CarPark.newBuilder().setCarParkId(14).setStatus("Spaces").setLocation("Behind Building 1").build()); } } Any suggestions would be much appreciated.
You might need synchronize Car.getInstance() method, because without proper synchronization, if it is called by different threads it may surprisingly return different instances! public static synchronized Car getInstance() { if(carparkCar == null) { carparkCar = new Car(); } return carparkCar; } Also your Car class is not thread-safe because it extends ArrayList which is not thread-safe. You should let your Car class extend something like ConcurrentLinkedQueue instead, or let your Car class compose a field of list = Collections.synchronizedList(new ArrayList()) instead of extending ArrayList.
Java Web Service SOAP with Tomcat
I have this problem: I'm created a web service in NetBeans IDE and TomCat as a server. This is my web service: #WebService(serviceName = "wsEagle_au") public class wsEagle_au { private pSession psession; #WebMethod(operationName = "log_in") public ArrayList log_in(#WebParam(name = "NICK_USER") String NICK_USER,#WebParam(name = "HASH_USER") String HASH_USER)throws Exception { psession=new pSession(); return psession.log_in(NICK_USER.toUpperCase(), HASH_USER); } } and this is the method where the arraylist is filled: public ArrayList log_in(mSession msession) throws JSONException { try { cfunctions=new cFunctions(msession.getNICK_USER()); msession.setHASH_USER(cfunctions.crypt(msession.getHASH_USER())); res_array=new ArrayList(); res_jobject=new JSONObject(); sqlquery="sqlQuery"; sql.getConnection(); sql.prepareStatement(sqlquery); sql.setString(1,msession.getNICK_USER()); sql.setString(2,msession.getHASH_USER()); datareader=sql.executeQuery(); if(datareader!=null&&datareader.next()){ res_jobject.put("ID_USER",datareader.getInt("ID_USER")); res_jobject.put("NAME_USER",datareader.getString("NAME_USER")); res_jobject.put("CNCIASIDN",datareader.getInt("CNCIASIDN")); res_jobject.put("SUSUUSID",datareader.getInt("SUSUUSID")); res_array.add(res_jobject); } else { //Password o User incorrect res_array.clear(); res_jobject=new JSONObject(); res_jobject.put("error","002"); res_array.add(res_jobject); } } catch(Exception ex) { //Inesperate error. res_array=new ArrayList(); res_jobject=new JSONObject(); res_jobject.put("error","002"); res_array.add(res_jobject); } return res_array; } When I tested with SOAP UI, I obtained this response: SOAPUI RESPONSE How can I return the arraylist?
Not able to load application.conf from cron job in play framework 2.4
I have created a cron job that start during application restart but when i tried to create db connection i am geeting null pointer exception. I am able to create and use db from other module using same configuration. Below is my Application.conf db.abc.driver=com.mysql.jdbc.Driver db.abc.url="jdbc:mysql://localhost:3306/db_name?useSSL=false" db.abc.username=root db.abc.password="" db.abc.autocommit=false db.abc.isolation=READ_COMMITTED And code that tried to access db is public class SchduleJob extends AbstractModule{ #Override protected void configure() { bind(JobOne.class) .to(JobOneImpl.class) .asEagerSingleton(); } } #ImplementedBy(JobOneImpl.class) public interface JobOne {} #Singleton public class JobOneImpl implements JobOne { final ActorSystem actorSystem = ActorSystem.create("name"); final ActorRef alertActor = actorSystem.actorOf(AlertActor.props); public JobOneImpl() { scheduleJobs(); } private Cancellable scheduleJobs() { return actorSystem.scheduler().schedule( Duration.create(0, TimeUnit.MILLISECONDS), //Initial delay 0 milliseconds Duration.create(6, TimeUnit.MINUTES), //Frequency 30 minutes alertActor, "alert", actorSystem.dispatcher(), null ); } } public class AlertActor extends UntypedActor{ public static Props props = Props.create(AlertActor.class); final ActorSystem actorSystem = ActorSystem.create("name"); final ActorRef messageActor = actorSystem.actorOf(MessageActor.props()); #Override public void onReceive(Object message) throws Exception { if(message != null && message instanceof String) { RequestDAO requestDAO = new RequestDAO(); try { List<DBRow> rows = requestDAO.getAllRow(); } catch(Exception exception) { exception.printStackTrace(); } } } } public class RequestDAO { public List<DBRow> getAllRow() throws Exception { List<DBRow> rows = new ArrayList<DBRow>(); Connection connection = null; try { connection = DB.getDataSource("abc").getConnection(); connection.setAutoCommit(false); } catch(Exception exception) { exception.printStackTrace(); if(connection != null) { connection.rollback(); } else { System.out.println("in else***********"); } return null; } finally { if(connection != null) connection.close(); } return schools; } When i am calling method getAllRow() of RequestDAO class it's throwing java.lang.NullPointerException at play.api.Application$$anonfun$instanceCache$1.apply(Application.scala:235) at play.api.Application$$anonfun$instanceCache$1.apply(Application.scala:235) at play.utils.InlineCache.fresh(InlineCache.scala:69) at play.utils.InlineCache.apply(InlineCache.scala:55) at play.api.db.DB$.db(DB.scala:22) at play.api.db.DB$.getDataSource(DB.scala:41) at play.api.db.DB.getDataSource(DB.scala) at play.db.DB.getDataSource(DB.java:33) But same code is working without cron job. What should i do to remove this error
Play uses the Typesafe config library for configuration. I suspect your current working directory from the cron script isn't set, so it's probably not finding your application.conf (application.properties) file. However, Config is nice in that it allows you to specify where to look for the file, either by its base name (to choose among .conf | .properties | .json extensions) or the filename including the extension on the java command line: To specify the base name, use -Dconfig.resource=/path/to/application To specify the full name, use -Dconfig.file=/path/to/application.properties
Alljoyn framework - Java - Signals . BUS_NO_SUCH_INTERFACE
It's a quite specific question but after days stuck in the same place and not getting any response in the Alljoyn forum, I decided to post it here. Maybe someone worked with this framework. I am doing a project and I need the use of the signal mechanish that Alljoyn framework provides. However, I do need the signals inside a session and the example provides in the api core is sessionless. In my case I need the service (server) to raise a signal and the client to receive it, but I am getting this error. Following the api samples, I managed to create a simple app that exchange messages through the methods defined in the interface, so I know that the communication is working. In this case, the service waits until the client connects and the send the signal. The client joins the session and right after register the signal and I am getting the BUS_NO_SUCH_INTERFACE error. I tried also to register after and before sending the signal, same problem. I think that for some reason the client does not find the bussignalhandler but I don't know why. I also put it in an external class and it didn't work. I'm following the example in the core api guide: https://allseenalliance.org/developers/develop/api-guide/core/android This is the part where the service register and emit the signal: SignalEmitter emitter = new SignalEmitter(mySignalInterface, joinerName, sessionId, SignalEmitter.GlobalBroadcast.Off); myInterface = emitter.getInterface(SampleInterface.class); // Emitting signals myInterface.buttonClicked(1); myInterface.playerPosition(12, 1, -24); However, in that example, I can't see a definition for myInterface. and I know it is not a mistake and they meant mySignalInterface because the method getInterface asks for an interface object and mySignalInterface is a class which implements that interface. I put here the example I created and I'll upload the files in case someone wants to try them. #BusInterface(name = "org.alljoyn.bus.samples.simple.SimpleInterface") public interface SimpleInterface { #BusMethod String Ping(String inStr) throws BusException; #BusSignal public void playerPosition(int x, int y, int z) throws BusException; } Service: Class inside the service to implement the signal and method class SimpleService implements SimpleInterface, BusObject { public String Ping(String inStr) { mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_PING, inStr)); return inStr; } public void playerPosition(int x, int y, int z) { /* no implementation needed here*/} } Here part of the code that makes the connection in the service: case CONNECT: { org.alljoyn.bus.alljoyn.DaemonInit.PrepareDaemon(getApplicationContext()); mBus = new BusAttachment(getPackageName(), BusAttachment.RemoteMessage.Receive); mBus.registerBusListener(new BusListener()); Status status = mBus.registerBusObject(mSimpleService, "/SimpleService"); if (status != Status.OK) {...} status = mBus.connect(); logStatus("BusAttachment.connect()", status); if (status != Status.OK) {...} int flag = 0; status = mBus.requestName(SERVICE_NAME, flag); logStatus(String.format("BusAttachment.requestName(%s, 0x%08x)", SERVICE_NAME, flag), status); if (status == Status.OK) { status = mBus.advertiseName(SERVICE_NAME, SessionOpts.TRANSPORT_ANY); logStatus(String.format("BusAttachement.advertiseName(%s)", SERVICE_NAME), status); if (status != Status.OK) {...} } Mutable.ShortValue contactPort = new Mutable.ShortValue(CONTACT_PORT); SessionOpts sessionOpts = new SessionOpts(); sessionOpts.traffic = SessionOpts.TRAFFIC_MESSAGES; sessionOpts.isMultipoint = false; sessionOpts.proximity = SessionOpts.PROXIMITY_ANY; sessionOpts.transports = SessionOpts.TRANSPORT_ANY + SessionOpts.TRANSPORT_WFD; status = mBus.bindSessionPort(contactPort, sessionOpts, new SessionPortListener() { #Override public boolean acceptSessionJoiner(short sessionPort, String joiner, SessionOpts sessionOpts) { return sessionPort == CONTACT_PORT; } #Override public void sessionJoined(short port, int id, String s) { sessionId = id; joinerName = s; sessionEstablished = true; } }); logStatus(String.format("BusAttachment.bindSessionPort(%d, %s)", contactPort.value, sessionOpts.toString()), status); if (status != Status.OK) {...} try { while (!sessionEstablished) { Thread.sleep(10); } SignalEmitter emitter = new SignalEmitter(mSimpleService, joinerName, sessionId, SignalEmitter.GlobalBroadcast.Off); SimpleInterface myInterface = emitter.getInterface(SimpleInterface.class); myInterface.playerPosition(12,1,1); } catch (BusException ex) {... } } Client: /*On create of the activity which has a button and a text view to send text to the server */ mEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() { public boolean onEditorAction(TextView view, int actionId, KeyEvent event) { if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_UP) { /* Call the remote object's Ping method. */ Message msg = mBusHandler.obtainMessage(BusHandler.PING, view.getText().toString()); mBusHandler.sendMessage(msg); } return true; } }); private static final String SERVICE_NAME = "org.alljoyn.bus.samples.simple"; private static final short CONTACT_PORT=42; private BusAttachment mBus; private ProxyBusObject mProxyObj; private SimpleInterface mSimpleInterface; case CONNECT: { org.alljoyn.bus.alljoyn.DaemonInit.PrepareDaemon(getApplicationContext()); mBus = new BusAttachment(getPackageName(), BusAttachment.RemoteMessage.Receive); mBus.registerBusListener(new BusListener() { #Override public void foundAdvertisedName(String name, short transport, String namePrefix) { if(!mIsConnected) { Message msg = obtainMessage(JOIN_SESSION); msg.arg1 = transport; msg.obj = name; sendMessage(msg); } } }); Status status = mBus.connect(); logStatus("BusAttachment.connect()", status); if (Status.OK != status) {...} status = mBus.findAdvertisedName(SERVICE_NAME); logStatus(String.format("BusAttachement.findAdvertisedName(%s)", SERVICE_NAME), status); if (Status.OK != status) {...} break; } case (JOIN_SESSION): { if (mIsStoppingDiscovery) { break; } short contactPort = CONTACT_PORT; SessionOpts sessionOpts = new SessionOpts(); sessionOpts.transports = (short)msg.arg1; Mutable.IntegerValue sessionId = new Mutable.IntegerValue(); Status status = mBus.joinSession((String) msg.obj, contactPort, sessionId, sessionOpts, new SessionListener() { #Override public void sessionLost(int sessionId, int reason) { mIsConnected = false; logInfo(String.format("MyBusListener.sessionLost(sessionId = %d, reason = %d)", sessionId,reason)); mHandler.sendEmptyMessage(MESSAGE_START_PROGRESS_DIALOG); } }); if (status == Status.OK) { mProxyObj = mBus.getProxyBusObject(SERVICE_NAME, "/SimpleService", sessionId.value, new Class<?>[] { SimpleInterface.class }); mSimpleInterface = mProxyObj.getInterface(SimpleInterface.class); mSessionId = sessionId.value; mIsConnected = true; mHandler.sendEmptyMessage(MESSAGE_STOP_PROGRESS_DIALOG); } break; status = mBus.registerSignalHandlers(this); if (status != Status.OK) {...} } case PING: { try { if (mSimpleInterface != null) { sendUiMessage(MESSAGE_PING, msg.obj); String reply = mSimpleInterface.Ping((String) msg.obj); sendUiMessage(MESSAGE_PING_REPLY, reply); } catch {...} } ...here some more code... #BusSignalHandler(iface="org.alljoyn.bus.samples.simple.SimpleInterface", signal="playerPosition") public void playerPosition(int x, int y, int z) { sendUiMessage(MESSAGE_POST_TOAST, "Signal captured"); } In this example, I have my client which has a textview where I can add text and send a ping to the server. This is working if I get rid of the registering signal part. I tried to do it as the api core says, with the Thread.sleep but doesn't work either. Here I add the code of both of my applications (client & server) based on the samples that are in the alljoyn api. https://github.com/JavierT/Alljoyn_signal_sample Please let me know if you have some doubts, it was hard to put all the information in one post. Thank you in advance.
I think this should solve your problem Alljoyn BusSignalHandler either of the following may be used to annotate a signal handler: #BusSignalHandler(iface = "org.sample.MyInterface", signal = "MySignal") public void handleSignal(String str) { } #BusSignalHandler(iface = "org.myapp.IMyInterface", signal = "EmitMySignal") public void handleSignal(String str) { } The first example may be used succesfully when IMyInterface is known to the BusAttachment via a previous call to BusAttachment.registerBusObject(BusObject, String) or BusAttachment.getProxyBusObject(String, String, int, Class[]). The second example may be used succesfully when IMyInterface is unknown to the BusAttachment. using the second example should solve your problem. Also, in your Client program as per the link provided above, #BusSignalHandler(iface="org.alljoyn.bus.samples.simple.SimpleInterface", signal="playerPosition") should be replaced with #BusSignalHandler(iface="org.alljoyn.bus.samples.simpleclient.SimpleInterface", signal="playerPosition")
When you call registerSignalHandlers you must pass an object that implements the interface SimpleInterface and the method playerPosition will be called in that object when you receives a signal. I believe (I've read the code quickly, I hope I'm not wrong) that you pass your BusHandler object, which does not implements SimpleInterface.
Please change : private static final String SERVICE_NAME = "org.alljoyn.bus.samples.simple"; to "org.alljoyn.bus.samples.simple.SimpleInterface" as you have interface name , both should be same . as when the Get method of BusObject is called the interface names does not match.
Handling Exception custom in JAX-WS
I have web service, developed using JAX-WS. Now i wanted to throw SOAPFault with customized error codes on certain conditions. I have a webfault: #WebFault(name = "BankExceptionFault1_Fault", targetNamespace = NS.namespace) public class BankException extends Exception { private WebMethodStatus faultInfo; public BankException(Errors error) { this(error, error.name()); } public WebMethodStatus getFaultInfo() { return faultInfo; } public BankException(Errors error, String description) { super(error.getErrorCode()); this.faultInfo = new WebMethodStatus(error, description); } } And In some method, for a given condition, throws exception: #Override #WebMethod(operationName = "UpdateAccountRecord") #WebResult(name = "Result") #LogExecution public WebMethodStatus updateAccountRecord( #WebParam(name = "Request") UpdateAccountRequest request) throws BankException { if (!Boolean.parseBoolean(specialMode)) { throw new BankException(Errors.INVALID_RUNNING_MODE, "Can't update account record. For updating need special running mode"); } service.updateAccountRecord(request); return new WebMethodSuccessStatus(); } In spring-mvc app, I want to catch my exception: try { wsPort.updateAccountRecord(updateAccountRequest); } catch (BankException e) { throwException(e); } catch(RemoteAccessException e){ throwException(e); } But always return RemoteAccessException, if try to update account using sring-mvc app. detailMessage:Could not access remote service at [http://localhost:8080/my-app-2.1.1-SNAPSHOT/app/MyApp] cause: java.lang.IllegalStateException: Current event not START_ELEMENT or END_ELEMENT But if I use soapui for update account, returns correct exception: BNK00017 Can't update account record. For updating need special running mode
If wsPort is something like an injected JaxWsPortProxyFactoryBean, then it's likely that your exception is being wrapped by RemoteAccessException. Try using RemoteAccessException.getCause() and see what you get...