Hello,

I’m afraid that this isn’t the right way to design a remote service, nor is it 
a particularly good way to design a service API.

When designing an API it is important to separate the functions of the API from 
the data that those functions act upon and return. In this case you have 
created an additional service interface for the data (a car) meaning that cars 
from one implementation are not the same as cars from another implementation. 
It also means that the Car data objects can have behaviour. This isn’t ideal, 
as it starts to mix the service data model with the implementation’s behaviour.

When using Remote Services there are many possible ways for data to be 
serialised and deserialised, however all deserialisation mechanisms 
fundamentally rely on the fact that they have access to a concrete type to 
deserialise into. Because the API returns an interface, not a concrete type 
this means that the service interface cannot be used to find the concrete type. 
Also, as there is no implementation of the interface visible to the client, it 
doesn’t even work if the server sends the name of the implementation class!

The correct way to design a Remoteable Service (or pretty much any service) is 
to be much stricter about the data structures consumed and returned by the 
service. You can read about the “basic types” supported by Remote Services 
<https://osgi.org/specification/osgi.cmpn/7.0.0/service.remoteservices.html#service.remoteservices-osgi.basic>.
 Aries RSA also supports asynchronous calls 
<https://osgi.org/specification/osgi.cmpn/7.0.0/service.remoteservices.html#d0e1407>.
 By eliminating behaviour from the data structures you pass then they can 
become a formal part of your API, eliminating the need to use an interface. You 
can see an example of this in the OSGi enRoute Microservice example 
<https://enroute.osgi.org/tutorial/030-tutorial_microservice.html#the-dao-api>

Best Regards,

Tim

> On 23 Jul 2018, at 10:30, ceugster <[email protected]> wrote:
> 
> I have three bundles: an api bundle with simple interface Car (one attribute
> "name") and a service interface with methods createCar and getCars. An jpa
> bundle that implements these interfaces and a consumer bundle, that lists
> the cars, when activated. When all bundles are in the same karaf instance,
> then everything works fine (thanks to jbonofre). Now I've extended the car
> service implementation with the properties "service.exported.interfaces=*"
> and "aries.rsa.port=8201" as in the aries echo example to add remote service
> capability and started the consumer (service component) bundle in a separat
> karaf instance. Starting this bundle is ok, it logs, that it gets a
> reference to the carService. When the component activates it calls
> carService.getCars(). When there are no cars yet, it displays "0 cars
> found", that's ok. When I add cars to the database in the server instance
> and refresh the consumer bundle, then I get an exception saying, that class
> CarImpl could not be found (see below). My question is: Why the consumer
> needs a CarImpl instance? Is the interface car not enough? If so, how I
> group the bundles in meaningful way to fulfill this requirement?
> 
> 2018-07-23T11:13:39,731 | ERROR | pipe-start 79    | consumer                 
>        
> |  -  -  | bundle example.consumer:1.0.0
> (79)[org.example.consumer.CarConsumer(6)] : The activate method has thrown
> an exception
> org.osgi.framework.ServiceException: Error calling 192.168.1.33:8201 method:
> getCars
>       at
> org.apache.aries.rsa.provider.tcp.TcpInvocationHandler.handleSyncCall(TcpInvocationHandler.java:115)
> ~[?:?]
>       at
> org.apache.aries.rsa.provider.tcp.TcpInvocationHandler.invoke(TcpInvocationHandler.java:66)
> ~[?:?]
>       at com.sun.proxy.$Proxy63.getCars(Unknown Source) ~[?:?]
>       at org.example.consumer.CarConsumer.activate(CarConsumer.java:38) ~[?:?]
>       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
>       at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
> ~[?:?]
>       at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> ~[?:?]
>       at java.lang.reflect.Method.invoke(Method.java:498) ~[?:?]
>       at
> org.apache.felix.scr.impl.inject.methods.BaseMethod.invokeMethod(BaseMethod.java:228)
> ~[52:org.apache.felix.scr:2.1.0]
>       at
> org.apache.felix.scr.impl.inject.methods.BaseMethod.access$500(BaseMethod.java:41)
> ~[52:org.apache.felix.scr:2.1.0]
>       at
> org.apache.felix.scr.impl.inject.methods.BaseMethod$Resolved.invoke(BaseMethod.java:664)
> ~[52:org.apache.felix.scr:2.1.0]
>       at
> org.apache.felix.scr.impl.inject.methods.BaseMethod.invoke(BaseMethod.java:510)
> [52:org.apache.felix.scr:2.1.0]
>       at
> org.apache.felix.scr.impl.inject.methods.ActivateMethod.invoke(ActivateMethod.java:317)
> [52:org.apache.felix.scr:2.1.0]
>       at
> org.apache.felix.scr.impl.inject.methods.ActivateMethod.invoke(ActivateMethod.java:307)
> [52:org.apache.felix.scr:2.1.0]
>       at
> org.apache.felix.scr.impl.manager.SingleComponentManager.createImplementationObject(SingleComponentManager.java:334)
> [52:org.apache.felix.scr:2.1.0]
>       at
> org.apache.felix.scr.impl.manager.SingleComponentManager.createComponent(SingleComponentManager.java:114)
> [52:org.apache.felix.scr:2.1.0]
>       at
> org.apache.felix.scr.impl.manager.SingleComponentManager.getService(SingleComponentManager.java:947)
> [52:org.apache.felix.scr:2.1.0]
>       at
> org.apache.felix.scr.impl.manager.SingleComponentManager.getServiceInternal(SingleComponentManager.java:919)
> [52:org.apache.felix.scr:2.1.0]
>       at
> org.apache.felix.scr.impl.manager.AbstractComponentManager.activateInternal(AbstractComponentManager.java:750)
> [52:org.apache.felix.scr:2.1.0]
>       at
> org.apache.felix.scr.impl.manager.AbstractComponentManager.enableInternal(AbstractComponentManager.java:661)
> [52:org.apache.felix.scr:2.1.0]
>       at
> org.apache.felix.scr.impl.manager.AbstractComponentManager.enable(AbstractComponentManager.java:427)
> [52:org.apache.felix.scr:2.1.0]
>       at
> org.apache.felix.scr.impl.manager.ConfigurableComponentHolder.enableComponents(ConfigurableComponentHolder.java:665)
> [52:org.apache.felix.scr:2.1.0]
>       at
> org.apache.felix.scr.impl.BundleComponentActivator.initialEnable(BundleComponentActivator.java:339)
> [52:org.apache.felix.scr:2.1.0]
>       at 
> org.apache.felix.scr.impl.Activator.loadComponents(Activator.java:381)
> [52:org.apache.felix.scr:2.1.0]
>       at org.apache.felix.scr.impl.Activator.access$200(Activator.java:49)
> [52:org.apache.felix.scr:2.1.0]
>       at
> org.apache.felix.scr.impl.Activator$ScrExtension.start(Activator.java:263)
> [52:org.apache.felix.scr:2.1.0]
>       at
> org.apache.felix.scr.impl.AbstractExtender.createExtension(AbstractExtender.java:196)
> [52:org.apache.felix.scr:2.1.0]
>       at
> org.apache.felix.scr.impl.AbstractExtender.modifiedBundle(AbstractExtender.java:169)
> [52:org.apache.felix.scr:2.1.0]
>       at
> org.apache.felix.scr.impl.AbstractExtender.modifiedBundle(AbstractExtender.java:49)
> [52:org.apache.felix.scr:2.1.0]
>       at
> org.osgi.util.tracker.BundleTracker$Tracked.customizerModified(BundleTracker.java:482)
> [?:?]
>       at
> org.osgi.util.tracker.BundleTracker$Tracked.customizerModified(BundleTracker.java:415)
> [?:?]
>       at org.osgi.util.tracker.AbstractTracked.track(AbstractTracked.java:232)
> [?:?]
>       at
> org.osgi.util.tracker.BundleTracker$Tracked.bundleChanged(BundleTracker.java:444)
> [?:?]
>       at
> org.apache.felix.framework.EventDispatcher.invokeBundleListenerCallback(EventDispatcher.java:915)
> [?:?]
>       at
> org.apache.felix.framework.EventDispatcher.fireEventImmediately(EventDispatcher.java:834)
> [?:?]
>       at
> org.apache.felix.framework.EventDispatcher.fireBundleEvent(EventDispatcher.java:516)
> [?:?]
>       at org.apache.felix.framework.Felix.fireBundleEvent(Felix.java:4579) 
> [?:?]
>       at org.apache.felix.framework.Felix.startBundle(Felix.java:2174) [?:?]
>       at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:998) 
> [?:?]
>       at org.apache.karaf.bundle.command.Start.executeOnBundle(Start.java:38)
> [16:org.apache.karaf.bundle.core:4.2.1.SNAPSHOT]
>       at
> org.apache.karaf.bundle.command.BundlesCommand.doExecute(BundlesCommand.java:65)
> [16:org.apache.karaf.bundle.core:4.2.1.SNAPSHOT]
>       at
> org.apache.karaf.bundle.command.BundlesCommand.execute(BundlesCommand.java:55)
> [16:org.apache.karaf.bundle.core:4.2.1.SNAPSHOT]
>       at
> org.apache.karaf.shell.impl.action.command.ActionCommand.execute(ActionCommand.java:84)
> [34:org.apache.karaf.shell.core:4.2.1.SNAPSHOT]
>       at
> org.apache.karaf.shell.impl.console.osgi.secured.SecuredCommand.execute(SecuredCommand.java:68)
> [34:org.apache.karaf.shell.core:4.2.1.SNAPSHOT]
>       at
> org.apache.karaf.shell.impl.console.osgi.secured.SecuredCommand.execute(SecuredCommand.java:86)
> [34:org.apache.karaf.shell.core:4.2.1.SNAPSHOT]
>       at org.apache.felix.gogo.runtime.Closure.executeCmd(Closure.java:599)
> [34:org.apache.karaf.shell.core:4.2.1.SNAPSHOT]
>       at 
> org.apache.felix.gogo.runtime.Closure.executeStatement(Closure.java:526)
> [34:org.apache.karaf.shell.core:4.2.1.SNAPSHOT]
>       at org.apache.felix.gogo.runtime.Closure.execute(Closure.java:415)
> [34:org.apache.karaf.shell.core:4.2.1.SNAPSHOT]
>       at org.apache.felix.gogo.runtime.Pipe.doCall(Pipe.java:416)
> [34:org.apache.karaf.shell.core:4.2.1.SNAPSHOT]
>       at org.apache.felix.gogo.runtime.Pipe.call(Pipe.java:229)
> [34:org.apache.karaf.shell.core:4.2.1.SNAPSHOT]
>       at org.apache.felix.gogo.runtime.Pipe.call(Pipe.java:59)
> [34:org.apache.karaf.shell.core:4.2.1.SNAPSHOT]
>       at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:?]
>       at
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
> [?:?]
>       at
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
> [?:?]
>       at java.lang.Thread.run(Thread.java:748) [?:?]
> Caused by: java.lang.ClassNotFoundException: org.example.impl.CarImpl
>       at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[?:?]
>       at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[?:?]
>       at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:?]
>       at
> org.apache.felix.framework.BundleWiringImpl.doImplicitBootDelegation(BundleWiringImpl.java:1859)
> ~[?:?]
>       at
> org.apache.felix.framework.BundleWiringImpl.tryImplicitBootDelegation(BundleWiringImpl.java:1788)
> ~[?:?]
>       at
> org.apache.felix.framework.BundleWiringImpl.searchDynamicImports(BundleWiringImpl.java:1741)
> ~[?:?]
>       at
> org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1617)
> ~[?:?]
>       at
> org.apache.felix.framework.BundleWiringImpl.access$200(BundleWiringImpl.java:80)
> ~[?:?]
>       at
> org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:2053)
> ~[?:?]
>       at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:?]
>       at java.lang.Class.forName0(Native Method) ~[?:?]
>       at java.lang.Class.forName(Class.java:348) ~[?:?]
>       at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:686)
> ~[?:?]
>       at
> org.apache.aries.rsa.provider.tcp.ser.BasicObjectInputStream.resolveClass(BasicObjectInputStream.java:56)
> ~[?:?]
>       at 
> java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1866)
> ~[?:?]
>       at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1749)
> ~[?:?]
>       at
> java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2040)
> ~[?:?]
>       at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1571)
> ~[?:?]
>       at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431) 
> ~[?:?]
>       at java.util.ArrayList.readObject(ArrayList.java:797) ~[?:?]
>       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
>       at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
> ~[?:?]
>       at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> ~[?:?]
>       at java.lang.reflect.Method.invoke(Method.java:498) ~[?:?]
>       at 
> java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1158)
> ~[?:?]
>       at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2176)
> ~[?:?]
>       at
> java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2067)
> ~[?:?]
>       at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1571)
> ~[?:?]
>       at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431) 
> ~[?:?]
>       at
> org.apache.aries.rsa.provider.tcp.TcpInvocationHandler.parseResult(TcpInvocationHandler.java:139)
> ~[?:?]
>       at
> org.apache.aries.rsa.provider.tcp.TcpInvocationHandler.handleSyncCall(TcpInvocationHandler.java:111)
> ~[?:?]
>       ... 54 more
> 
> Thanks!
> 
> 
> 
> --
> Sent from: http://karaf.922171.n3.nabble.com/Karaf-User-f930749.html

Reply via email to