I have following code:
main:
#SpringBootApplication
#EnableAsync
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
In some place I have code like this:
public enum EmailMessage {
....
void sendSilent(String from, String[] recipients, Map<String, ?> properties) {
long start= System.currentTimeMillis();
try {
emailService.sendEmail(from, this.subject, recipients, properties, this.templateFileName);
} catch (Exception e) {
LOGGER.warn("Could not send email", e);
}
finally {
System.out.println("Result:" + (System.currentTimeMillis()- start)/1000 + " Thread:" + Thread.currentThread().getId());
System.out.println();
}
}
}
Here I am setting emailService:
#Service
public static class EmailService {
#PostConstruct
public void initialize() {
//to provide reference to EmailService to enum because enum could not be component
EmailMessage.emailService = this;
}
....
}
sendEmail:
#Async
public void sendEmail(String from, String subject, String[] to, Map<String, ?> props, String templateFileName) throws Exception {
.... //here some which executes slowly
System.out.println( " sendEmail Thread:" + Thread.currentThread().getId());
}
The code I provided produces following output:
sendEmail Thread:1
Result:9 Thread:1
As you can see thread the same for both methods. And code executes 9 sec.
What do I wrong?
Related
My Timer task is not functioning as it's supposed to. I have scheduled it to repeat a specific task every 3 seconds but this is not happening.
As per Java documentations:
schedule(TimerTask task, long delay,long period) .
Schedules the specified task for repeated fixed-delay execution, beginning after the specified delay. Subsequent executions take place at approximately regular intervals separated by the specified period.
public class Tester {
public static void main(String[] args) {
log.info("Schedule task");
Timer time = new Timer();
TesterClient tc = new TesterClient();
time.schedule(tc, 0, 3000);
}
}
public class TesterClient extends TimerTask {
public void init() {
System.out.println("New Task!!!!");
}
#Override
public void run() {
init();
}
}
And yet i only get one "New Task!!!!" printed in console
Am i missing something here?
Thanks
Update:
I will try to paste in here every piece of code that is relevant and goes from top to bottom in terms of execution.
Start:
public class Tester {
public static Logger log = Logger.getLogger("com.orderlysoftware.orderlycalls.manager.ManagerClient");
public static Timer time = new Timer();
public static void main(String[] args) {
log.info("Creating service");
Service.serviceInit();
log.info("Initializing TesterClient for scheduled task");
TesterClient tc = new TesterClient();
time.schedule(tc, 0, 3000);
}
public static ManagerSettings managerSettings() {
ManagerSettings managerSettings = new ManagerSettings();
managerSettings.setName("managerClient");
managerSettings.setHost("77.237.251.152");
managerSettings.setPort(5038);
managerSettings.setUsername("orderlystats");
managerSettings.setPassword("orderlystats");
return managerSettings;
}
}
Service class method:
static ExecutorService executorService;
{
serviceInit();
}
//public static ClassLoader loader;
public static void serviceInit(){
if(executorService!=null) {
return;
}
executorService= Executors.newCachedThreadPool();
try {
ThreadPoolExecutor tpe=(ThreadPoolExecutor)executorService;
tpe.setMaximumPoolSize(100000);
} catch (Exception ex) {
System.out.println(ex);
}
}
package com.orderlysoftware.testing;
import java.io.IOException;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.logging.Logger;
import com.orderlysoftware.orderlycalls.OrderlyCalls;
import com.orderlysoftware.orderlycalls.asterisk.manager.ManagerClient;
import com.orderlysoftware.orderlycalls.asterisk.manager.action.ManagerResponse;
import com.orderlysoftware.orderlycalls.asterisk.manager.event.ManagerEvent;
import com.orderlysoftware.orderlycalls.asterisk.manager.event.ManagerEventListener;
import com.orderlysoftware.orderlycalls.base.Service;
public class TesterClient extends TimerTask {
public static Logger log = Logger.getLogger("com.orderlysoftware.orderlycalls.manager.ManagerClient");
public static ExecutorService es = Service.getExecutorService();
public ManagerClient mc;
public void init() {
log.info("run check method to see if Manager Client is running");
boolean running = check();
log.info("checker status is : " + running);
while(running) {
try {
Thread.sleep(3000);
startCall();
} catch (InterruptedException e) {
log.info("Sleep interrupted");
}
}
}
public boolean check() {
log.info("ManagerClient is: " + mc);
if(mc == null) {
log.info("Initialize service");
mc = (ManagerClient)OrderlyCalls.createService(ManagerClient.class, Tester.managerSettings());
log.info("Initialize ManagerClient");
mc.init();
log.info("Service created. ManagerClient initialized : "+ mc);
}
if(!mc.isConnected()) {
log.info("ManagerClient is not connected");
return false;
}
log.info("Check if ManagerClient is connected AND running");
if(mc.isConnected() && !mc.isRunning()) {
log.info("Manager Client is connected but NOT running");
return false;
}
if(mc.isConnected() && mc.isRunning()) {
log.info("ManagerClient is connected and running");
return true;
}
return false;
}
private void startCall() {
log.info("Adding listener to the call");
addListenerToCall(mc);
int testID = 0;
ManagerResponse response = null;
try {
response = mc.originate("Local/1001#main", "1001", "main", "1", null, null, 2500, "1002", "testID=" + (testID++), "1", true);
log.info("Manager response is: " + response);
if(response == null) {
mc.shutdown();
throw new IOException("Null response for originate.");
}
if(!response.getValue("Response").equals("Success")) {
mc.shutdown();
throw new IOException("Originate returned " + response.getValue("Response") + ": " + response.getValue("Message"));
}
} catch (IOException e) {
log.info("IO Exception" + e.toString());
}
}
public void addListenerToCall(ManagerClient mc) {
try {
// Add event listener
log.info("Adding ManagerEventListener to ManagerClient: " + mc);
mc.addManagerEventListener(new ManagerEventListener() {
#Override
public void handleManagerEvent(ManagerEvent event) {
if("OriginateResponse".equals(event.getType())) {
handleOriginateResponse(event);
}
}
});
} catch (IOException e) {
log.info("IO Exception : " + e);
}
}
protected void handleOriginateResponse(ManagerEvent event) {
try {
// do something here
Thread.sleep(1000);
} catch (InterruptedException e) {
log.info("sleep interupted" + e);
}
}
#Override
public void run() {
log.info("New Task!!!!!!!!!!");
init();
}
}
It works for me - but I suspect the problem is that you're letting the Timer get garbage collected:
After the last live reference to a Timer object goes away and all outstanding tasks have completed execution, the timer's task execution thread terminates gracefully (and becomes subject to garbage collection). However, this can take arbitrarily long to occur.
As noted in comments, I believe that "outstanding tasks" means "tasks that have already been started" rather than just "ones which would be scheduled". The docs are unclear, however, and I may be mistaken.
If you prevent garbage collection (e.g. by keeping a reference to the Timer in a static variable) then I think you'll see it keep going forever...
Your program works fine for me too. The issue got reproduced with following change in your program:
import java.util.*;
public class Tester {
public static void main(String[] args) {
System.out.println("Schedule task");
Timer time = new Timer();
TesterClient tc = new TesterClient();
time.schedule(tc, 0, 3000);
}
}
class TesterClient extends TimerTask {
public void init() {
System.out.println("New Task!!!!");
}
#Override
public void run() {
init();
this.cancel(); //-------This causes hang in execution after printing once
}
}
But, not sure what could have caused this to happen without cancel() in your program.
I have a simple EJB , and when i run it through my standalone client every thing is working well,
But once i add an interceptor, The #PostConstruct in the EJB stops working:
package interceptor;
public class LogInterceptor {
#PostConstruct
public void init(InvocationContext context) {
System.out.println(new Date().toString() +" Entered interceptor");
}
#PreDestroy
public void aboutToBeRemoved(InvocationContext context) {
System.out.println(new Date().toString() + " Leaving interceptor");
}
#AroundInvoke
public Object gettingToBusiness(InvocationContext context) {
String methodName = context.getMethod().getName();
System.out.println("The method name is: " +methodName);
if (methodName.equals("add")) {
}
try {
return context.proceed();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
My test client:
public class Test {
public static void main(String[] args){
InitialContext ctx=getInitialContext();
ListRemote stub=null;
try {
stub = (ListRemote)ctx.lookup("ejb:/Lab12/ListEJB!interceptor.ListRemote?stateful");
} catch (NamingException e) {
System.out.println("Lookup Failed");
e.printStackTrace();
}
System.out.println("Adding data");
stub.add("Hello");
stub.add("-");
stub.add("World");
stub.add("!!!");
System.out.println("Getting data :");
for(Object o:stub.getAll()){
System.out.print(o+" ");
}
System.out.println("Removing '-' element");
stub.remove(1);
System.out.println("Getting data again:");
for(Object o:stub.getAll()){
System.out.print(o+" ");
}
stub.destroy();
}
public static InitialContext getInitialContext(){
Properties properties = new Properties();
properties.put(Context.URL_PKG_PREFIXES , "org.jboss.ejb.client.naming");
try {
return new InitialContext(properties);
} catch (NamingException e) {
System.out.println("Cannot generate InitialContext");
e.printStackTrace();
}
return null;
}
}
My EJB:
#Stateful(name="ListEJB")
#Interceptors({LogInterceptor.class})
public class ListBean implements ListRemote{
private ArrayList<Serializable> list;
#PostConstruct
public void init(){
System.out.println("In it init ---------------------------------------------------");
list=new ArrayList<Serializable>();
}
public void add(Serializable object){
System.out.println("Currently in the list is: " +list);
System.out.println("The object is: " +object);
list.add(object);
System.out.println("Added");
}
public Serializable get(int index){
return list.get(index);
}
public void remove(int index){
list.remove(index);
}
public Object[] getAll(){
return list.toArray();
}
#Remove
public void destroy(){
list=null;
}
}
Why does it disables my EJB #PostConstruct ?
In this code:
#PostConstruct
public void init(InvocationContext context) {
System.out.println(new Date().toString() +" Entered interceptor");
}
You are intercepting the PostConstruct of the original EJB and not letting it pass. If you want to pass it through to the target EJB, you need to call proceed:
#PostConstruct
public void init(InvocationContext context) {
System.out.println(new Date().toString() +" Entered interceptor");
context.proceed();
}
Same applies for your PreDestroy. Basically it applies to all intercepted methods. See the EJB3 specification, section 12.5 (page 308):
Interceptor methods must always call InvocationContext.proceed() or no
subsequent interceptor methods or bean business method or lifecycle
callback methods will be invoked.
I'm computing a future for having a timeout in waiting for a serial event to happen:
Future<Response> future = executor.submit(new CommunicationTask(this, request));
response = new Response("timeout");
try {
response = future.get(timeoutMilliseconds, TimeUnit.MILLISECONDS);
} catch (InterruptedException | TimeoutException e) {
future.cancel(true);
log.info("Execution time out." + e);
} catch (ExecutionException e) {
future.cancel(true);
log.error("Encountered problem communicating with device: " + e);
}
The CommunicationTask class has implemented the Observer interface to listen to an change from the serial port.
The problem is that reading from the serial port is relatively slow and even when a serial event is happening the time runs out and a TimeoutException is thrown. What can I do to stop the timeout clock of my future when a serial event is happening?
I tried it with an AtomicReference but that didn't change anything:
public class CommunicationTask implements Callable<Response>, Observer {
private AtomicReference atomicResponse = new AtomicReference(new Response("timeout"));
private CountDownLatch latch = new CountDownLatch(1);
private SerialPort port;
CommunicationTask(SerialCommunicator communicator, Request request) {
this.communicator = communicator;
this.message = request.serialize();
this.port = communicator.getPort();
}
#Override
public Response call() throws Exception {
return query(message);
}
public Response query(String message) {
communicator.getListener().addObserver(this);
message = message + "\r\n";
try {
port.writeString(message);
} catch (Exception e) {
log.warn("Could not write to port: " + e);
communicator.disconnect();
}
try {
latch.await();
} catch (InterruptedException e) {
log.info("Execution time out.");
}
communicator.getListener().deleteObserver(this);
return (Response)atomicResponse.get();
}
#Override
public void update(Observable o, Object arg) {
atomicResponse.set((Response)arg);
latch.countDown();
}
}
What can I do to solve this problem?
EDIT:
Ok I had one error. I was counting down my latch befor setting the atomicResponse in my update function. Now it seems to work, but there's still the question if this approach is the right way to do so?
have you explored google's Guava 'future listener', it is based on Async future, hope following code snippet helps you....
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
public class SyncFutureExample {
public static void main(String[] args) {
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(1));
ListenableFuture<String> lf = service.submit(new CommuncationTask());
//no need for future.get() or future.get(10,time minutes)
//add callbacks(= async future listeners) ....
Futures.addCallback(lf, new FutureCallback<String>() {
public void onSuccess(String input) {
System.out.println(input + " >>> success");//gets a callback once task is success
}
public void onFailure(Throwable thrown) {
System.out.println(thrown + " >>> failure");//gets a callback if task is failed
}
});
service.shutdown();
}
}
class CommuncationTask implements Callable<String>{
public String call() throws Exception {
TimeUnit.SECONDS.sleep(15);// some dummy serious task .............
return "TaskDone";
}
}
Hope this will help. I won't comment on it in the hopes that everything is clear from the code.
class CommunicationTask implements Callable<String>, Observer {
volatile boolean ignoreTimeoutException;
public CommunicationTask(SerialCommunicator communicator, Request request) {
}
public String call() throws Exception {
Thread.sleep(1000);
return "done";
}
public void update(Observable o, Object arg) {
ignoreTimeoutException = true;
}
}
class FutureCommunicationTask extends FutureTask<String> {
private CommunicationTask ct;
public FutureCommunicationTask(CommunicationTask ct) {
super(ct);
this.ct = ct;
}
public String get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
try {
return super.get(timeout, unit);
} catch (TimeoutException e) {
if (ct.ignoreTimeoutException) {
return get(); // no timeout wait
}
throw e;
}
}
}
public class Test {
public static void main(String[] args) throws Exception {
CommunicationTask ct = new CommunicationTask(null, null);
FutureTask<String> fct = new FutureCommunicationTask(ct);
ExecutorService ex = Executors.newSingleThreadExecutor();
ex.execute(fct);
// uncomment this line and timeout will be cancelled
ct.update(null, null);
String res = fct.get(1, TimeUnit.MILLISECONDS);
System.out.println(res);
}
}
My Java application requires a retry logic on remote calls failures.
These remote calls are:
scattered all over the application
pertain to different Remote Service classes.
Also, the retry logic may have varying retry interval and varying retry attempts.
I need a generic retry() implementation which can make appropriate method calls depending on from where it is called. Below is a simple code illustration of I am looking for. I know we can attempt to do this using java reflection, but, is there a framework or an open source available somewhere which is read-to-use?
try {
ClassA objA = remoteServiceA.call(paramA1, paramA2, ...);
} catch (Exception e){
ClassA objA = (ClassA)retry(remoteService, listOfParams, ..); // generic method call
}
..
try {
ClassB objB = remoteServiceB.call(paramB1, paramB2, ...);
} catch (Exception e){
ClassA objB = (ClassB)retry(remoteService, listOfParams, ..); // generic method call
}
As already suggested, you should use AOP and Java annotations. I would recommend a read-made mechanism from jcabi-aspects (I'm a developer):
#RetryOnFailure(attempts = 3, delay = 5)
public String load(URL url) {
return url.openConnection().getContent();
}
Read also this blog post: http://www.yegor256.com/2014/08/15/retry-java-method-on-exception.html
Update: Check RetryFunc from Cactoos.
This is a book example of where aspectj (or aop in general) can be used, see 8.2.7 Example in Spring documentation and 5 Reasons Java Developers Should Learn and Use AspectJ.
Basically an aspect intercepts all calls to given methods (specified using annotation, naming convention, whatever) and retries.
Assume you have a method, that need to retied at every 500ms and upto 5 times.
Current class:
public class RemoteCaller{
Service serviceCaller;
public void remoteCall(String message) {
serviceCaller.updateDetails( this.message);
return null;
}
}
Modified approach:
public class RetriableHelper<T> implements Callable<T> {
private Callable<T> task;
private int numberOfRetries;
private int numberOfTriesLeft;
private long timeToWait;
public RetriableHelper(int numberOfRetries, long timeToWait, Callable<T> task) {
this.numberOfRetries = numberOfRetries;
numberOfTriesLeft = numberOfRetries;
this.timeToWait = timeToWait;
this.task = task;
}
public T call() throws Exception {
while (true) {
try {
return task.call();
} catch (InterruptedException e) {
throw e;
} catch (CancellationException e) {
throw e;
} catch (Exception e) {
numberOfTriesLeft--;
if (numberOfTriesLeft == 0) {
throw e;
}
Thread.sleep(timeToWait);
}
}
}
}
Backend system/remote call class:
public class RemoteCaller{
Service serviceCaller;
public void remoteCall(String message) {
class RemoteCallable implements Callable<Void> {
String message;
public RemoteCallable( String message)
{
this.message = message;
}
public Void call() throws Exception{
serviceCaller.updateDetails( this.message);
return null;
}
}
RetriableHelper<Void> retriableHelper = new RetriableHelper<Void>(5, 500, new RemoteCallable( message));
try {
retriableHelper.call();
} catch (Exception e) {
throw e;
}
}
}
enter link description here Spring has a retry annotation which servers the purpose
Step 1: Add following dependency to your POM
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.1.5.RELEASE</version>
</dependency>
Step 2: Enabling Spring Retry
To enable Spring Retry in an application, we need to add the #EnableRetry annotation to our #Configuration class:
Ex:
#Configuration
#EnableRetry
public class AppConfig { ... }
Step 3: To add retry functionality to methods, #Retryable can be used:
Ex:
#Service
public interface MyService {
#Retryable(
value = { SQLException.class },
maxAttempts = 2,
backoff = #Backoff(delay = 5000))
void retryService(String sql) throws SQLException;
...
}
Step 4.The #Recover annotation is used to define a separate recovery method when a #Retryable method fails with a specified exception:
Ex:
#Service
public interface MyService {
...
#Recover
void recover(SQLException e, String sql);
}
See Url for more details : http://www.baeldung.com/spring-retry
where do you get the services from? use a factory to Proxy the service you get from the original factory. The proxy can then implement the retry transparently. See the java Proxy/ProxyGenerators in reflection.
If you are using spring , then better go with Aspects.
Otherwise, below sample solution can work:
public class Test
{
public static void main(String[] args) throws Exception
{
Test test = new Test();
test.toRunFirst("Hello! This is normal invocation");
runWithRetry(test, "toRunFirst", "Hello! This is First, called with retry");
runWithRetry(test, "toRunSecond", "Hello! This is Second, called with retry");
}
public void toRunFirst(String s) {
System.out.println(s);
}
public void toRunSecond(String s) {
System.out.println(s);
}
public static Object runWithRetry(Object obj, String methodName, Object... args) throws Exception
{
Class<?>[] paramClass = new Class<?>[args.length];
for(int i=0; i< args.length; i++) {
paramClass[i] = args[i].getClass();
}
Method method = obj.getClass().getDeclaredMethod(methodName, paramClass);
int retryCount = 2;
for(int i=0; i< retryCount; i++) {
try {
return method.invoke(obj, args);
}
catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
}
I did not find what I needed so there is mine.
The main feature is that it throws the type of Exception you need when maxRetries is reached so you can catch it in the call.
import org.apache.log4j.Logger;
public class TaskUtils {
public static <E extends Throwable> void retry(int maxRetries, Task<E> task) throws E {
retry(maxRetries, 0, null, task);
}
public static <E extends Throwable> void retry(int maxRetries, long waitTimeMs, Logger logger, Task<E> task) throws E {
while (maxRetries > 0) {
maxRetries--;
try {
task.run();
} catch (Exception e) {
if (maxRetries == 0) {
try {
throw e;
} catch (Exception ignored) { // can't happen but just in case we wrap it in
throw new RuntimeException(e);
}
}
if (logger != null)
logger.warn("Attempt " + maxRetries + " failed", e);
try {
Thread.sleep(waitTimeMs);
} catch (InterruptedException ignored) {
}
}
}
}
public interface Task<E extends Throwable> {
void run() throws E;
}
}
Usage :
TaskUtils.retry(3, 500, LOGGER, () -> stmClickhouse.execute(
"ALTER TABLE `" + database + "`.`" + table.getName() + "` ON CLUSTER " + clusterName + allColumnsSql
));
add it into pom.xml
<dependency>
<groupId>org.deking.utils</groupId>
<artifactId>retry</artifactId>
<version>0.0.2-SNAPSHOT</version>
</dependency>
new Retry<String>()
.maxOperationWaitTime(30_000)//Max operation wait time during a single operation
.retryIntervalTime(1_000)//Interval time between two operations
.maxRetryTimes(3)//Retry times when operation failed(or timeout) at the first time
.operation(() -> {
//your operation
return "success!";
})
.judgement(t -> (t == null || t.isEmpty()))//add your judgement whether the operation should be retry(Operation should return a value)
.execute();
If you want add retry config annotation on method,and call it:
class RetryTests{
#RetryConfig( maxRetryTimes=1)
public static String TestAnnotation() {
return "aaa";
}
public static void main(String[] args) {
try {
new Retry<String>()
.of(RetryTest.class.getMethod("TestAnnotation"),null)
.judgement(r -> r.equals("aaa"))
.execute();
} catch (NoSuchMethodException | SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
For Example
SvrInterface si1 = (SvrInterface) Naming.lookup(Address);
SvrInterface si2 = (SvrInterface) Naming.lookup(Address);
si1.setUser ("User1");
si2.setUser ("User2");
And Next
String si1User = si1.getUser();
Will the result of si1User become "User1" ?
The simple answer in your case is No. You're still referencing the same remote object in registry bound to the address. Good place to begin learning more about RMI architecture > here.
EDIT 1
Simple RMI Factory example I whipped up quickly...
EchoService
public interface EchoService extends Remote, Serializable{
String echo(String msg) throws RemoteException;
String getUser() throws RemoteException;
void setUser(String user) throws RemoteException;
}
EchoServiceImpl
public class EchoServiceImpl extends UnicastRemoteObject implements EchoService {
private static final long serialVersionUID = -3671463448485643888L;
private String user;
public EchoServiceImpl() throws RemoteException {
super();
}
#Override
public String echo(String msg) throws RemoteException {
return this.user + ": " + msg;
}
#Override
public String getUser() throws RemoteException {
return this.user;
}
#Override
public void setUser(String user) throws RemoteException {
this.user = user;
}
}
EchoServiceFactory
public interface EchoServiceFactory extends Remote {
EchoService createEchoService() throws RemoteException;
}
EchoServiceFactoryImpl
public class EchoServiceFactoryImpl extends UnicastRemoteObject implements
EchoServiceFactory {
private static final long serialVersionUID = 6625883990856972736L;
protected EchoServiceFactoryImpl() throws RemoteException {
super();
System.setProperty("java.rmi.server.codebase", EchoServiceFactory.class.getProtectionDomain().getCodeSource().getLocation().toString());
System.setProperty("java.security.policy", "/java.policy");
if (System.getSecurityManager() == null) {
System.setSecurityManager(new SecurityManager());
}
try {
Registry registry = LocateRegistry.getRegistry("localhost");
registry.rebind("EchoService", this);
System.out.println("Echo service factory registered.");
} catch (Exception e) {
System.err.println("Error registering echo service factory: "
+ e.getMessage());
}
}
#Override
public EchoService createEchoService() throws RemoteException {
return new EchoServiceImpl();
}
public static void main(String[] args) {
try {
new EchoServiceFactoryImpl();
} catch (RemoteException e) {
System.err.println("Error creating echo service factory: "
+ e.getMessage());
}
}
}
EchoServiceClient
public class EchoServiceClient {
public static void main(String[] args) {
try {
System.setProperty("java.security.policy", "/java.policy");
if (System.getSecurityManager() == null) {
System.setSecurityManager(new SecurityManager());
}
Registry registry = LocateRegistry.getRegistry("localhost");
EchoServiceFactory serviceFactory =
(EchoServiceFactory) registry.lookup("EchoService");
EchoService echoServiceX = serviceFactory.createEchoService();
echoServiceX.setUser("Tom");
System.out.println(echoServiceX.echo("Hello!"));
EchoService echoServiceY =
serviceFactory.createEchoService();
echoServiceY.setUser("Jerry");
System.out.println(echoServiceY.echo("Hello"));
System.out.println(echoServiceX.echo("Hey There!!!"));
System.out.println(echoServiceY.echo(":o)"));
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
}
Running the client produce output as below.
Tom: Hello!
Jerry: Hello
Tom: Hey There!!!
Jerry: :o)