blob: 936e58261d94a4025e4b4ad796cb17a90cee3c65 [file] [log] [blame]
/*
* 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());
}
}