At present I have server(service) client(activity) working project which are operated in a same process. I am trying to move the server to a new process by adding android:process=":seperateService" in the manifest.
However, after successful bind to service, in function
public void onServiceConnected(ComponentName arg0, IBinder arg1)
the arg1 parameter received is null. This appears only when the service is made to have separates processes.
what am i missing?
solved by using:
aidl = binder.Stub.asInterface(arg1);
instead of:
aidl = (binder) arg1;
but not sure of why this is was not problem when both client and server in same process.
Related
I have service which runs some init scripts after application startup (implemented with ApplicationListener<ApplicationReadyEvent>). In this scripts I need to call another services with RestTemplate which is #LoadBalanced. When the call to service is invoked there's no information about instances of remote service because discovery server was not contacted at that time (I guess).
java.lang.IllegalStateException: No instances available for api-service
at org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient.execute(RibbonLoadBalancerClient.java:79)
So is there way how to get list of available services from discovery server at application startup, before my init script will execute?
Thanks
edit:
The problem is more related to fact, that in current environment (dev) all services are tied together in one service (api-service). So from within api-service I'm trying to call #LoadBalanced client api-service which doesn't know about self? Can I register some listener or something similar to know when api-service (self) will be available?
here are the sample applications. I'm mainly interested how to have working this method
edit2:
Now there could be the solution to create EurekaListener
public static class InitializerListener implements EurekaEventListener {
private EurekaClient eurekaClient;
private RestOperations restTemplate;
public InitializerListener(EurekaClient eurekaClient, RestOperations restTemplate) {
this.eurekaClient = eurekaClient;
this.restTemplate = restTemplate;
}
#Override
public void onEvent(EurekaEvent event) {
if (event instanceof StatusChangeEvent) {
if (((StatusChangeEvent) event).getStatus().equals(InstanceInfo.InstanceStatus.UP)) {
ResponseEntity<String> helloResponse = restTemplate.getForEntity("http://api-service/hello-controller/{name}", String.class, "my friend");
logger.debug("Response from controller is {}", helloResponse.getBody());
eurekaClient.unregisterEventListener(this);
}
}
}
}
and then register it like this:
EurekaEventListener initializerListener = new InitializerListener(discoveryClient, restTemplate);
discoveryClient.registerEventListener(initializerListener);
However this is only executed only when application is registered to discovery service first time. Next time when I stop the api-service and run it again, event is not published. Is there any other event which can I catch?
Currently, in Camden and earlier, applications are required to be registered in Eureka before they can query for other applications. Your call is likely too early in the registration lifecycle. There is an InstanceRegisteredEvent that may help. There are plans to work on this in the Dalston release train.
I am trying Ribbon configuration with RestTemplate based on bookmark service example but without luck, here is my code:
#SpringBootApplication
#RestController
#RibbonClient(name = "foo", configuration = SampleRibbonConfiguration.class)
public class BookmarkServiceApplication {
public static void main(String[] args) {
SpringApplication.run(BookmarkServiceApplication.class, args);
}
#Autowired
RestTemplate restTemplate;
#RequestMapping("/hello")
public String hello() {
String greeting = this.restTemplate.getForObject("http://foo/hello", String.class);
return String.format("%s, %s!", greeting);
}
}
with error page as below:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Tue Mar 22 19:59:33 GMT+08:00 2016
There was an unexpected error (type=Internal Server Error, status=500).
No instances available for foo
but if I remove annotation #RibbonClient, everything will be just ok,
#RibbonClient(name = "foo", configuration = SampleRibbonConfiguration.class)
and here is SampleRibbonConfiguration implementation:
public class SampleRibbonConfiguration {
#Autowired
IClientConfig ribbonClientConfig;
#Bean
public IPing ribbonPing(IClientConfig config) {
return new PingUrl();
}
#Bean
public IRule ribbonRule(IClientConfig config) {
return new AvailabilityFilteringRule();
}
}
Is it because RibbonClient can not work with RestTemplate together?
and another question is that does Ribbon configuration like load balancing rule could be configured via application.yml configuration file?
as from Ribbon wiki, seems we can configure Ribbon parameters like NFLoadBalancerClassName, NFLoadBalancerRuleClassName etc in property file, does Spring Cloud also supports this?
I'm going to assume you're using Eureka for Service Discovery.
Your particular error:
No instances available for foo
can happen for a couple of reasons
1.) All services are down
All of the instances of your foo service could legitimately be DOWN.
Solution: Try visiting your Eureka Dashboard and ensure all the services are actually UP.
If you're running locally, the Eureka Dashboard is at http://localhost:8761/
2.) Waiting for heartbeats
When you very first register a service via Eureka, there's a period of time where the service is UP but not available. From the documentation
A service is not available for discovery by clients until the
instance, the server and the client all have the same metadata in
their local cache (so it could take 3 heartbeats)
Solution: Wait a good 30 seconds after starting your foo service before you try calling it via your client.
In your particular case I'm going to guess #2 is likely what's happening to you. You're probably starting the service and trying to call it immediately from the client.
When it doesn't work, you stop the client, make some changes and restart. By that time though, all of the heartbeats have completed and your service is now available.
For your second question. Look at the "Customizing the Ribbon Client using properties" section in the reference documentation. (link)
I am new to java RMI, actually I wrote, compiled and started rmic, and also tried to start server but failed due to _stub 'ClassNotFound' exception..... I'm using java 7... I searched a lot on Google but nobody told step by step example that could work...I got some idea about stteing codebase and security policy but not very clear suggestion that how to do it.. please help telling me steps including command-line .......... please... I have everything just tell me how to start server, and required settings like codebase or policy settings etc... Thanks
You don't need to use rmic. Instead, create your server object and call one of the exportObject() method overloads that has the port parameter. For example,
MyRemoteIntf stub = UnicastRemoteObject.exportObject(server, 0);
This will cause RMI to generate the stub automatically. (The documentation is horribly unclear on this point. If you use the version without the port parameter, it will use only the old, rmic-generated stubs instead of generating them automatically.)
Also, make sure that your remote interface is in the codebase of both the registry and any clients. You'll get different errors if you haven't done this properly. This has been answered a bunch of times on Stackoverflow already; search for "rmi ClassNotFoundException".
There is no need to use the rmic command since java (J2SE) 5.0 the stubs are dynamically generated at runtime.
Here is a basic step by step example of how to use RMI.
First define the Remote interface that defines what the client can see and do:
public interface FooService extends Remote {
// Don't forget to add throws RemoteException.
public void bar() throws RemoteException;
}
NOTE: if you do not add throws RemoteException to the method declaration you will encounter the following exception:
java.lang.IllegalArgumentException: illegal remote method encountered: public abstract void RMIExample.FooService.bar()
After you defined what the client can do you must define the concrete implementation of the methods on the server slide:
public class FooServiceImpl extends UnicastRemoteObject implements FooService {
public FooServiceImpl() throws RemoteException {
super();
}
public void bar() {
System.out.println("I was remotely invoked!");
}
}
The implementation class must inherit from UnicastRemoteObject and implement the Remote interface you defined earlier and the class must have a constructor that throws RemoteException.
Now that you have fully defined the remote functionality you must bind the implementation object to a URL on the server side:
// 4000 is the port to listen on.
LocateRegistry.createRegistry(4000);
Naming.rebind("//127.0.0.1:4000/foobar", new FooServiceImpl());
Now that you have your server up and running you need a stub instance A.K.A a proxy in the client side:
FooService fooService =
(FooService)Naming.lookup("//127.0.0.1:4000/foobar");
and finally invoke the remote method:
fooService.bar();
the following should be printed on the server side:
I was remotely invoked!
References:
http://en.wikipedia.org/wiki/Java_remote_method_invocation
http://docs.oracle.com/javase/1.5.0/docs/guide/rmi/relnotes.html
I have a gwt-application and want to connect to it's xmlrpc backend via a standalone xmlrpc-client (written e.g. with Apaches' xmlrpc-library).
Assume the project creates a servlet called TestServlet connected to the URL /test/test providing a Method public int add(int a, int b).
Calling the deployed servlet (running in a jetty on port 8080) with the code shown below, I get this error message in jettys' log:
javax.servlet.ServletException: Content-Type was 'text/xml'. Expected 'text/x-gwt-rpc'.
Is there any easy way to connect such a standalone xmlrpc-client with the gwt-enhanced xmlrpc-server?
I read about xmlrpc-gwt - but I want to keept the gwt dependencies for that standalone client minimal.
XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
config.setServerURL(new URL("http://127.0.0.1:8080/test/test"));
config.setConnectionTimeout(60 * 1000);
config.setReplyTimeout(60 * 1000);
XmlRpcClient client = new XmlRpcClient();
client.setConfig(config);
Object[] params = new Object[] {new Integer(2), new Integer(3)});
Integer result = (Integer) client.execute("TestServlet.add", params);
System.out.println(result);
GWT's RPC protocol is not related to XML/RPC . It's loosely based on JSON but it is not considered public, so you should not rely on its current form for interoperability.
We have a workflow as webservice application. We use custom tracking profile for each workflow type.
The worklfow assembly version got changed, so I changed the profile version too. So as the older workflows should work fine.
Now I started the workflow runtime , a workflow got triggered and persisted to DB
After some time , i re-start the runtime, the workflow is re-hydrated, but try to invoke an event on workflow, it shows exception.
If The workflow engine is not re-started , everything works fine, no errors and workflow is completed.
System.Workflow.Activities.EventDeliveryFailedException: Event "Event_111" on interface type "Service.IService" for instance id "4d0b7397-4ce1-49c7-92c6-92405caa8fe4" cannot be delivered. ---> System.ArgumentNullException: Value cannot be null.
Parameter name: profile
at System.Workflow.Runtime.RTTrackingProfile..ctor(TrackingProfile profile, Activity root, Type serviceType)
at System.Workflow.Runtime.TrackingProfileManager.CreateProfile(TrackingProfile profile, Type workflowType, Type serviceType)
at System.Workflow.Runtime.TrackingProfileManager.GetProfile(TrackingService service, Activity workflow, Version versionId)
at System.Workflow.Runtime.TrackingListenerFactory.GetChannels(Activity schedule, WorkflowExecutor exec, Guid instanceID, Type workflowType, TrackingListenerBroker& broker)
at System.Workflow.Runtime.TrackingListenerFactory.GetListener(Activity sked, WorkflowExecutor skedExec, TrackingListenerBroker broker)
at System.Workflow.Runtime.TrackingListenerFactory.GetTrackingListener(Activity sked, WorkflowExecutor skedExec, TrackingListenerBroker broker)
at System.Workflow.Runtime.TrackingListenerFactory.WorkflowExecutorInitializing(Object sender, WorkflowExecutorInitializingEventArgs e)
at System.EventHandler`1.Invoke(Object sender, TEventArgs e)
at System.Workflow.Runtime.WorkflowRuntime.WorkflowExecutorCreated(WorkflowExecutor workflowExecutor, Boolean loaded)
at System.Workflow.Runtime.WorkflowExecutor.ReRegisterWithRuntime(WorkflowRuntime workflowRuntime)
at System.Workflow.Runtime.WorkflowRuntime.RegisterExecutor(Boolean isActivation, WorkflowExecutor executor)
at System.Workflow.Runtime.WorkflowRuntime.Load(Guid key, CreationContext context, WorkflowInstance workflowInstance)
at System.Workflow.Runtime.WorkflowRuntime.GetWorkflow(Guid instanceId)
at System.Workflow.Activities.WorkflowMessageEventHandler.EventHandler(Object sender, ExternalDataEventArgs eventArgs)
--- End of inner exception stack trace ---
at System.Workflow.Activities.WorkflowMessageEventHandler.EventHandler(Object sender, ExternalDataEventArgs eventArgs)
at RecipeChangeService.RecipeChangeService.MfgEngOrTLApproved(Guid instanceId, ResponseDataObject rdo) in E:\MES\trunk\DotNet\WorkflowDesignProject\WorkflowDesignProject\Workflow Types\RecipeChangeWF\RecipeChangeService.cs:line 64
Any ideas, what is getting wrong? There are two workflows of different versions, but attached to same profile version, can this be issue?
I found the solution for it. The version of tracking profile should match the version while creating tracking profile xml.
TrackingProfile myProfile = new TrackingProfile();
myProfile.Version = new Version("4.0.0.0");
The verison should be same as the version used in stored procedure "UpdateTrackingProfile"
This solved my problem.