使用Lingo增强JMS
虽然activemq+jencks的jms轻量级解决方案已经很好地在psa中work了,尤其spring的JmsTemplate使得代码更简单,但是还是存在问题。
问题来自暑期做psa的时候,linke突然提出要求,需要MDP返回些处理信息,比如处理结果、异常,以便后台监控和前台显示,但是,MDP没有返回值也没法返回异常,当时我只能无奈。
在下载了lingo-1.0-M1后(虽然1.2.1发布了,但是还没有文档支持,所以暂且用1.0),参考其自带的example,了解了它异步函数调用的代码思路。
callback实现了EventListener,提供了返回值和异常的接口,另外涉及到两个方面,首先,callback本身需要轮询,其次,callback可以由实例池管理。
第二个方面并没有利用实例池,而是利用ThreadPoolExecutor来newFixedThreadPool,管理不同的异步调用线程,来完成对callback的调度。
encoding="UTF-8"?>
BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
class="org.activemq.spring.BrokerFactoryBean">
<property name="config"
value="classpath:activemq.xml"
/>
</bean>
class="org.activemq.ActiveMQConnectionFactory">
<property
name="brokerURL">
<value>tcp://localhost:61616</value>
</property>
</bean>
class="org.activemq.message.ActiveMQQueue">
<constructor-arg
index="0">
<value>lingo.demo</value>
</constructor-arg>
</bean>
id="invocationFactory"
class="org.logicblaze.lingo.LingoRemoteInvocationFactory">
<constructor-arg>
<bean
class="org.logicblaze.lingo.SimpleMetadataStrategy">
<!-- 允许单向异步调用
-->
<constructor-arg
value="true" />
</bean>
</constructor-arg>
</bean>
<bean id="client"
class="org.logicblaze.lingo.jms.JmsProxyFactoryBean">
<property name="serviceInterface"
value="org.openepo.jms.lingo.MailService"
/>
<property name="connectionFactory"
ref="jmsFactory" />
<property name="destination"
ref="destination" />
-->
<property
name="remoteInvocationFactory"
ref="invocationFactory" />
</bean>
<bean id="server"
class="org.logicblaze.lingo.jms.JmsServiceExporter">
<property name="service"
ref="serverImpl" />
<property name="serviceInterface"
value="org.openepo.jms.lingo.MailService"
/>
<property name="connectionFactory"
ref="jmsFactory" />
<property name="destination"
ref="destination" />
<property name="invocationFactory"
ref="invocationFactory" />
</bean>
<bean id="serverImpl"
class="org.openepo.jms.lingo.MailServiceImpl"
/>
-->
<bean id="asyncManager"
class="org.openepo.jms.lingo.AsyncManager"
singleton="false">
<property name="mailClient" ref="client"
/>
<property name="threadSize" value="5"
/>
</bean>
public void onResult(Object result);
public void stop();
public void onException(Exception e);
}
import java.util.List;
{
private List results = new ArrayList();
private Object semaphore = new Object();
private boolean stopped;
private Exception onException;
private long waitTime = 1000;
public synchronized void onResult(Object result)
{
results.add(result);
synchronized (semaphore) {
semaphore.notifyAll();
}
}
// lifecycle end methods
public void stop() {
stopped = true;
}
{
onException = e;
}
{
return
onException;
}
{
return results;
}
{
return stopped;
}
messageCount) {
System.out.println("Waiting for: " + messageCount +
" responses to arrive");
System.currentTimeMillis();
< 10; i++) {
try {
if (hasReceivedResponses(messageCount))
{
break;
}
synchronized (semaphore) {
semaphore.wait(waitTime);
}
}
catch (InterruptedException e) {
System.out.println("Caught: " + e);
}
}
long end =
System.currentTimeMillis() - start;
System.out.println("End of wait for " + end + " millis");
}
{
return
results.isEmpty();
}
hasReceivedResponses(int messageCount) {
return results.size()
>= messageCount;
}
{
return waitTime;
}
{
this.waitTime =
waitTime;
}
}
public void
asyncSendMail(List<Mail> mails,
ResultListener listener);
}
{
asyncSendMail(List<Mail> mails,
ResultListener listener) {
try {
for (Mail mail : mails) {
sendMail(mail);
Thread.sleep(2000);// 服务端时耗
listener.onResult(mail.getContent() +
" Sended Successfully.");
}
listener.stop();
} catch
(Exception e) {
listener.onException(e);
}
}
Exception {
// 可以取消下面的注释来查看服务端将异常传给客户端
//throw new Exception("Error occurs
on server side.");
}
}
{
private static final long serialVersionUID = 1L;
private String content;
public String getContent() {
return content;
}
{
this.content = content;
}
this.content = content;
}
}
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
10; //callback池大小
(ThreadPoolExecutor) Executors
.newFixedThreadPool(threadSize); //callback池
{
AsyncManager.threadSize = threadSize;
}
{
this.mailClient = mailClient;
}
}
List<Mail> mails)
{
final ResultListenerImpl callBack = new
ResultListenerImpl();
callBack.setWaitTime(2000);
// 异步调用
mailClient.asyncSendMail(mails, callBack);
executor.execute(new Runnable()
{
public void run() {
// callBack 阻塞等待n个消息
callBack.waitForAsyncResponses(mails.size());
// 服务端异常
System.out.println("Server
Exception: "
+
callBack.getOnException().getMessage());
} else
{
// 得到服务端处理结果,打印结果
for (Object result :
callBack.getResults())
{
System.out.println("Result:
" + result);
}
}
}
});
}
}
上面匿名类的run方法中,在callback的waitForAsyncResponses方法结束后,可以检查callback中的信息,进行异常处理等。
@Test
public void test() {
List<Mail> mails = new
ArrayList<Mail>();
mails.add(new Mail("mail1"));
mails.add(new Mail("mail2"));
long startTime = System.currentTimeMillis();
try {
// 异步调用
asyncManager.sendMails(mails);
System.out.println("Cost time "
+ (System.currentTimeMillis() -
startTime) + "ms");
//为查看结果,sleep主线程
Thread.sleep(10000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
多出了许多代码,自然复杂度有所增加,但是lingo-1.2.1后,增加了annotation,减少了callback的代码量。
使用Lingo增强JMS的更多相关文章
- Spring 4.3.11.RELEASE文档阅读(一):overview
一.宏观概述中的体会和发现 Spring是组件式的框架,它允许我们只使用其一小部分.Spring所做的工作,就是不断的简化我们的操作.比如它的IOC容器,当我们自己应用设计模式,比如说:建造者.工厂. ...
- 详细介绍Spring 5的那些新特性与增强
Spring5 是一个重要的版本,距离SpringFramework4差不多四年.在此期间,大多数增强都是在 SpringBoot 项目中完成的.在本文中,我们将很快了解到Spring5发行版中的一些 ...
- J2EE相关概念,EJB/JNDI/JMS/RMI等
J2EE 四层模型 J2EE的核心API.组件.相关概念 JDBC(Java Database Connectivity) JNDI(Java Name and Directory Interface ...
- JMS规范与Kafka
一.为什么需要消息队列 消息队列的核心作用就是三点:解耦一个系统中各个子模块的互相绑定与依赖,异步执行后台耗时逻辑,并行处理一个请求中涉及的多个操作. 以我们常见的下订单场景来说明,我们熟悉的淘宝,后 ...
- JPA、JTA与JMS
三者都属于Java企业级规范 JPA(java persistence API) JPA 通过JDK5.0的注解或XML来描述 对象-关系表的映射关系,并将运行期的实体对象持久化存储到数据库中. JT ...
- Asynchronous calls and remote callbacks using Lingo Spring Remoting
http://www.jroller.com/sjivan/entry/asynchronous_calls_and_callbacks_using Asynchronous calls and re ...
- Lingo (Spring Remoting) : Passing client credentials to the server
http://www.jroller.com/sjivan/entry/lingo_spring_remoting_passing_client Lingo (Spring Remoting) : P ...
- java高级特性增强
第4天 java高级特性增强 今天内容安排: 1.掌握多线程 2.掌握并发包下的队列 3.了解JMS 4.掌握JVM技术 5.掌握反射和动态代理 java多线程增强 .1. java多线程基本知识 . ...
- 什么是JMS规范?
一.简介 JMS是什么:JMS是Java提供的一套技术规范和关于消息中间件的协议 JMS干什么用:通过生产者Producer,消息服务器,以及消费者通力合作,使异构系统能进行集成通信,缓解系统瓶颈,提 ...
随机推荐
- Public Private Protect Inheritance and access specifiers
In the previous lessons on inheritance, we've been making all of our data members public in order to ...
- FZU1920 Left Mouse Button(dfs)
Problem 1920 Left Mouse Button Accept: 385 Submit: 719 Time Limit: 1000 mSec Memory Limit : 3 ...
- C语言中函数和指针的參数传递
近期写二叉树的数据结构实验.想用一个没有返回值的函数来创建一个树,发现这个树就是建立不起来,那么我就用这个样例讨论一下c语言中指针作为形參的函数中传递中隐藏的东西. 大家知道C++中有引用的概念,两个 ...
- 【Linux】配置JAVA_HOME环境变量
1. 永久修改,对所有用户有效 # vi /etc/profile //按键盘[Shift + g], 在profile文件最后添加下面的内容: export JAVA_HOME = /home/my ...
- HttpClient4.3教程 第二章 连接管理
2.1.持久连接 两个主机建立连接的过程是很复杂的一个过程,涉及到多个数据包的交换,并且也很耗时间.Http连接需要的三次握手开销很大,这一开销对于比较小的http消息来说更大.但是如果我们直接使用已 ...
- Spring bean注入方式
版权声明:本文为博主原创文章,如需转载请标注转载地址. 博客地址:http://www.cnblogs.com/caoyc/p/5619525.html Spring bean提供了3中注入方式:属 ...
- RPM卸载
安全地卸载 rpm卸载软件包,并不是简单地将原来安装的文件逐个删除,那样做的话,可能会出现这样或那样的问题.如,a软件包依靠b软件包做某些工作,若b软件包卸载了,则a软件包就不能正常运行了.rpm为用 ...
- resin设置jvm参数
http://www.quiee.com.cn/archives/592/ resin resin3.0 及前期版本内存设置, 如下: 启动时设置虚拟内存: unix> bin/httpd.sh ...
- 【转】ESFramework成熟的C#网络通信框架(跨平台)
原文地址:http://www.cnblogs.com/zhuweisky/archive/2010/08/12/1798211.html ESFramework网络通信框架是一套性能卓越.稳定可靠. ...
- jQuery Autocomplete 用户快速找到并从预设值列表中选择
jQuery Autocomplete 插件根据用户输入值进行搜索和过滤,让用户快速找到并从预设值列表中选择.通过给 Autocomplete 字段焦点或者在其中输入字符,插件开始搜索匹配的条目并显示 ...