/* * 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()); } }