| /*
|
| * Copyright 1999-2011 Alibaba Group.
|
| *
|
| * Licensed under the Apache License, Version 2.0 (the "License");
|
| * you may not use this file except in compliance with the License.
|
| * You may obtain a copy of the License at
|
| *
|
| * http://www.apache.org/licenses/LICENSE-2.0
|
| *
|
| * Unless required by applicable law or agreed to in writing, software
|
| * distributed under the License is distributed on an "AS IS" BASIS,
|
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| * See the License for the specific language governing permissions and
|
| * limitations under the License.
|
| */
|
| package com.alibaba.dubbo.rpc.protocol.dubbo; |
| |
| |
| import java.io.Serializable;
|
| import java.lang.reflect.Method;
|
| import java.util.ArrayList;
|
| import java.util.HashMap;
|
| import java.util.List;
|
| import java.util.Map;
|
| import java.util.concurrent.Future;
|
| import java.util.concurrent.TimeUnit;
|
|
|
| import junit.framework.Assert;
|
|
|
| import org.junit.After;
|
| import org.junit.Before;
|
| import org.junit.Test;
|
|
|
| import com.alibaba.dubbo.common.Constants;
|
| import com.alibaba.dubbo.common.URL;
|
| import com.alibaba.dubbo.common.utils.NetUtils;
|
| import com.alibaba.dubbo.rpc.Exporter;
|
| import com.alibaba.dubbo.rpc.Invoker;
|
| import com.alibaba.dubbo.rpc.RpcContext;
|
| import com.alibaba.dubbo.rpc.StaticContext;
|
| import com.alibaba.dubbo.rpc.protocol.dubbo.support.ProtocolUtils;
|
| |
| public class ImplicitCallBackTest{ |
| |
| protected Exporter<IDemoService> exporter = null; |
| protected Invoker<IDemoService> reference = null; |
| |
| protected URL serviceURL = null ; |
| protected URL consumerUrl = null ; |
| Method onReturnMethod; |
| Method onThrowMethod ; |
| Method onInvokeMethod ; |
| |
| @Before |
| public void setUp() throws SecurityException, NoSuchMethodException{ |
| onReturnMethod = Nofify.class.getMethod("onreturn", new Class<?>[]{Person.class, Integer.class}); |
| onThrowMethod = Nofify.class.getMethod("onthrow", new Class<?>[]{Throwable.class, Integer.class}); |
| onInvokeMethod = Nofify.class.getMethod("oninvoke", new Class<?>[]{Integer.class}); |
| }
|
|
|
| @After
|
| public void tearDown(){
|
| ProtocolUtils.closeAll();
|
| } |
| |
| public void initOrResetService(){ |
| destroyService(); |
| exportService(); |
| referService(); |
| } |
| public void destroyService(){ |
| demoProxy = null ; |
| try { |
| if (exporter!=null) exporter.unexport(); |
| if (reference!=null) reference.destroy(); |
| }catch (Exception e) { |
| } |
| } |
| |
| void referService() { |
| demoProxy = (IDemoService)ProtocolUtils.refer(IDemoService.class, consumerUrl); |
| } |
| |
| public void exportService(){ |
| exporter = ProtocolUtils.export(new NormalDemoService(), IDemoService.class, serviceURL); |
| } |
| public void exportExService(){ |
| exporter = ProtocolUtils.export(new ExceptionDemoExService(), IDemoService.class, serviceURL); |
| } |
| |
| public void initOrResetUrl(boolean isAsync) throws Exception { |
| int port = NetUtils.getAvailablePort() ; |
| consumerUrl = serviceURL = URL.valueOf("dubbo://127.0.0.1:"+port+"/"+IDemoService.class.getName()+"?group=test&async="+isAsync+"&timeout=100000&reference.filter=future" ); |
| StaticContext.getSystemContext().clear(); |
| } |
| |
| public void initImplicitCallBackURL_onlyOnthrow() throws Exception { |
| StaticContext.getSystemContext().put(StaticContext.getKey(consumerUrl, "get", Constants.ON_THROW_METHOD_KEY),onThrowMethod); |
| StaticContext.getSystemContext().put(StaticContext.getKey(consumerUrl, "get", Constants.ON_THROW_INSTANCE_KEY),notify); |
| } |
| public void initImplicitCallBackURL_onlyOnreturn() throws Exception { |
| StaticContext.getSystemContext().put(StaticContext.getKey(consumerUrl, "get", Constants.ON_RETURN_METHOD_KEY),onReturnMethod); |
| StaticContext.getSystemContext().put(StaticContext.getKey(consumerUrl, "get", Constants.ON_RETURN_INSTANCE_KEY),notify); |
| |
| } |
| public void initImplicitCallBackURL_onlyOninvoke() throws Exception { |
| StaticContext.getSystemContext().put(StaticContext.getKey(consumerUrl, "get", Constants.ON_INVOKE_METHOD_KEY),onInvokeMethod); |
| StaticContext.getSystemContext().put(StaticContext.getKey(consumerUrl, "get", Constants.ON_INVOKE_INSTANCE_KEY),notify); |
| } |
| |
| //================================================================================================ |
| |
| NofifyImpl notify = new NofifyImpl(); |
| |
| interface Nofify { |
| public void onreturn(Person msg, Integer id); |
| public void onthrow(Throwable ex, Integer id); |
| public void oninvoke(Integer id); |
| } |
| class NofifyImpl implements Nofify{ |
| public List<Integer> inv = new ArrayList<Integer> (); |
| public Map<Integer ,Person> ret = new HashMap<Integer ,Person> (); |
| public Map<Integer ,Throwable> errors = new HashMap<Integer ,Throwable> (); |
| public boolean exd = false; |
| public void onreturn(Person msg, Integer id) { |
| System.out.println("onNotify:"+msg); |
| ret.put(id, msg); |
| } |
| public void onthrow(Throwable ex, Integer id) { |
| errors.put(id, ex); |
| // ex.printStackTrace(); |
| } |
| public void oninvoke(Integer id) { |
| inv.add(id); |
| } |
| } |
| |
| interface IDemoService{ |
| public Person get(int id); |
| } |
| |
| class NormalDemoService implements IDemoService { |
| public Person get(int id){ |
| return new Person(id, "charles", 4); |
| } |
| } |
| class ExceptionDemoExService implements IDemoService { |
| public Person get(int id){ |
| throw new RuntimeException("request persion id is :"+ id); |
| } |
| } |
| |
| public static class Person implements Serializable{ |
| private static final long serialVersionUID = 1L; |
| public Person(int id, String name, int age) { |
| this.id = id; |
| this.name = name; |
| this.age = age; |
| } |
| private int id; |
| private String name ; |
| private int age; |
| public String getName() { |
| return name; |
| } |
| public void setName(String name) { |
| this.name = name; |
| } |
| public int getAge() { |
| return age; |
| } |
| public void setAge(int age) { |
| this.age = age; |
| } |
| public int getId() { |
| return id; |
| } |
| public void setId(int id) { |
| this.id = id; |
| } |
| @Override |
| public String toString() { |
| return "Person [name=" + name + ", age=" + age + "]"; |
| } |
| } |
| //================================================================================================ |
| IDemoService demoProxy = null; |
| |
| @Test |
| public void test_CloseCallback() throws Exception { |
| initOrResetUrl(false); |
| initOrResetService() ; |
| Person ret = demoProxy.get(1); |
| Assert.assertEquals(1, ret.getId()); |
| destroyService(); |
| } |
| |
| @Test |
| public void test_Sync_Onreturn() throws Exception { |
| initOrResetUrl(false); |
| initImplicitCallBackURL_onlyOnreturn(); |
| initOrResetService() ; |
| int requestId = 2; |
| Person ret = demoProxy.get(requestId); |
| Assert.assertEquals(requestId, ret.getId()); |
| for (int i = 0; i < 10; i++) { |
| if (! notify.ret.containsKey(requestId)){ |
| Thread.sleep(200); |
| }else { |
| break; |
| } |
| } |
| Assert.assertEquals(requestId, notify.ret.get(requestId).getId()); |
| destroyService(); |
| } |
| |
| @Test |
| public void test_Ex_OnReturn() throws Exception { |
| initOrResetUrl(true); |
| initImplicitCallBackURL_onlyOnreturn(); |
| |
| destroyService(); |
| exportExService(); |
| referService(); |
| |
| int requestId = 2; |
| Person ret = demoProxy.get(requestId); |
| Assert.assertEquals(null, ret); |
| for (int i = 0; i < 10; i++) { |
| if (! notify.errors.containsKey(requestId)){ |
| Thread.sleep(200); |
| }else { |
| break; |
| } |
| } |
| Assert.assertTrue(! notify.errors.containsKey(requestId)); |
| destroyService(); |
| } |
| |
| @Test |
| public void test_Ex_OnInvoke() throws Exception { |
| initOrResetUrl(true); |
| initImplicitCallBackURL_onlyOninvoke(); |
| |
| destroyService(); |
| exportExService(); |
| referService(); |
| |
| int requestId = 2; |
| Person ret = demoProxy.get(requestId); |
| Assert.assertEquals(null, ret); |
| for (int i = 0; i < 10; i++) { |
| if (! notify.inv.contains(requestId)){ |
| Thread.sleep(200); |
| }else { |
| break; |
| } |
| } |
| Assert.assertTrue(notify.inv.contains(requestId)); |
| destroyService(); |
| } |
| |
| @Test |
| public void test_Ex_Onthrow() throws Exception { |
| initOrResetUrl(true); |
| initImplicitCallBackURL_onlyOnthrow(); |
| |
| destroyService(); |
| exportExService(); |
| referService(); |
| |
| int requestId = 2; |
| Person ret = demoProxy.get(requestId); |
| Assert.assertEquals(null, ret); |
| for (int i = 0; i < 10; i++) { |
| if (! notify.errors.containsKey(requestId)){ |
| Thread.sleep(200); |
| }else { |
| break; |
| } |
| } |
| Assert.assertTrue(notify.errors.containsKey(requestId)); |
| Assert.assertTrue(notify.errors.get(requestId) instanceof Throwable); |
| destroyService(); |
| } |
| |
| @Test |
| public void test_Sync_NoFuture() throws Exception { |
| initOrResetUrl(false); |
| initImplicitCallBackURL_onlyOnreturn(); |
| destroyService(); |
| exportService(); |
| referService(); |
| |
| int requestId = 2; |
| Person ret = demoProxy.get(requestId); |
| Assert.assertEquals(requestId, ret.getId()); |
| Future<Person> pFuture = RpcContext.getContext().getFuture(); |
| Assert.assertEquals(null, pFuture); |
| destroyService(); |
| } |
| |
| @Test |
| public void test_Async_Future() throws Exception { |
| initOrResetUrl(true); |
| destroyService(); |
| exportService(); |
| referService(); |
| |
| int requestId = 2; |
| Person ret = demoProxy.get(requestId); |
| Assert.assertEquals(null, ret); |
| Future<Person> pFuture = RpcContext.getContext().getFuture(); |
| ret = pFuture.get(1000, TimeUnit.MICROSECONDS); |
| Assert.assertEquals(requestId, ret.getId()); |
| destroyService(); |
| } |
| |
| @Test |
| public void test_Async_Future_Multi() throws Exception { |
| initOrResetUrl(true); |
| destroyService(); |
| exportService(); |
| referService(); |
| |
| int requestId1 = 1; |
| Person ret = demoProxy.get(requestId1); |
| Assert.assertEquals(null, ret); |
| Future<Person> p1Future = RpcContext.getContext().getFuture(); |
| |
| int requestId2 = 1; |
| Person ret2 = demoProxy.get(requestId2); |
| Assert.assertEquals(null, ret2); |
| Future<Person> p2Future = RpcContext.getContext().getFuture(); |
| |
| ret = p1Future.get(1000, TimeUnit.MICROSECONDS); |
| ret2 = p2Future.get(1000, TimeUnit.MICROSECONDS); |
| Assert.assertEquals(requestId1, ret.getId()); |
| Assert.assertEquals(requestId2, ret.getId()); |
| destroyService(); |
| } |
| |
| @Test(expected = RuntimeException.class) |
| public void test_Async_Future_Ex() throws Exception { |
| try{ |
| initOrResetUrl(true); |
| destroyService(); |
| exportExService(); |
| referService(); |
| |
| int requestId = 2; |
| Person ret = demoProxy.get(requestId); |
| Assert.assertEquals(null, ret); |
| Future<Person> pFuture = RpcContext.getContext().getFuture(); |
| ret = pFuture.get(1000, TimeUnit.MICROSECONDS); |
| Assert.assertEquals(requestId, ret.getId()); |
| }finally{ |
| destroyService(); |
| } |
| } |
| |
| @Test(expected = RuntimeException.class) |
| public void test_Normal_Ex() throws Exception { |
| initOrResetUrl(false); |
| destroyService(); |
| exportExService(); |
| referService(); |
| |
| int requestId = 2; |
| Person ret = demoProxy.get(requestId); |
| Assert.assertEquals(requestId, ret.getId()); |
| } |
| } |