如果 bean 部署在同一个应用程序服务器中,一个线程用于更多 bean?
A thread for more beans if beans are deployed in the same application server?
我正在尝试使用 Java EE 实现(练习)主动复制算法。
我遇到了一个意想不到的问题。
我有这个功能(伪代码):
public boolean doOperation() in the frontEnd EJB{
sendJMSMessageToTopic(); //publish new command to the replica
Thread.sleep(200);
readFromQueue(); //read Ack from replica
control if write quorum is reached
commit or abort
return state (success or not)
}
问题是:
回调 onMessage() 已调用,但在 doOperation 的同一次调用中未收到响应。
当我再次调用 doOperation 时,我读取了先前调用 doOperation 方法的响应。
我使用 glassfish,并将所有组件部署在同一个应用程序服务器中。
我使用主题将请求发布到副本,并使用队列接收来自副本的响应。 FrontEnd 是 Singleton,Replicas 是 Message Drive Bean。
更新:我
我的副本代码
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package EJBData;
import Service.ResponceMessage;
import Service.Command;
import Service.Product;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.inject.Inject;
import javax.jms.JMSConnectionFactory;
import javax.jms.JMSContext;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
/**
*
* @author melix
*/
@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"),
@ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "TopicRepliche"),
//@ActivationConfigProperty(propertyName = "subscriptionDurability", propertyValue = "durable"),
@ActivationConfigProperty(propertyName = "clientId", propertyValue = "TopicRepliche"),
@ActivationConfigProperty(propertyName = "subscriptionName", propertyValue = "TopicRepliche")
})
public class Replica1 implements MessageListener {
@Resource(mappedName = "QueueFrontEnd")
private Queue queueFrontEnd;
@Inject
@JMSConnectionFactory("java:comp/DefaultJMSConnectionFactory")
private JMSContext context;
private final int R_CONTAINS_KEY=0;
private final int W_REMOVE_KEY=1;
private final int W_PUT=2;
private final int R_GET=3;
private final int R_UPDATE_PRICE=4;
private final int R_GENERATE_JSON_FROM_MAP=5;
private final int COD_REPLICA=0;
private final ConcurrentHashMap<Integer,Product> item_map=new ConcurrentHashMap<>();
private final ConcurrentHashMap<Long,Command> pending_command=new ConcurrentHashMap<>();
private long last_cmd_executed=0;
private long last_cmd_received=0;
private synchronized void setLastCmdExecuted(long last_cmd_executed){
this.last_cmd_executed=last_cmd_executed;
}
private synchronized void setLastCmdReceived(long last_cmd_received){
this.last_cmd_received=last_cmd_received;
}
public boolean containsKey(int key){
return item_map.containsKey(key);
}
public boolean removeKey(int key){
item_map.remove(key);
return true;
}
public boolean put(Product b){
item_map.put(Integer.parseInt(b.getId()),b);
return true;
}
public Product get(int key){
return item_map.get(key);
}
public void updatePrice(){
for (Map.Entry pairs : item_map.entrySet()) {
int key=(int)pairs.getKey();
Product p=(Product)pairs.getValue();
double price=p.getInitialPrice();
item_map.remove(key);
System.out.println(price);
if(price>=5)
p.setInitialPrice(price-5);
else
p.setInitialPrice(0);
item_map.put(key, p);
}
}
public String generateJSONFromMap(){
String json="[";
for (Map.Entry pairs : item_map.entrySet()) {
Product p=(Product)pairs.getValue();
json+=p.toString();
json+=",";
}
if(json.endsWith(","))
json = json.substring(0,json.length() - 1);
json+="]";
return json;
}
public Replica1() {
}
@Override
public void onMessage(Message message) {
Command c;
if (message instanceof ObjectMessage) {
try {
Object object = ((ObjectMessage) message).getObject();
c=(Command)object;
int command_type=c.getType();
Object res=null;
switch(command_type){
case R_CONTAINS_KEY:
res=containsKey((int)c.getInput());
break;
case W_REMOVE_KEY:
res=removeKey((int)c.getInput());
break;
case W_PUT:
res=put((Product)c.getInput());
break;
case R_GET:
res=get((int)c.getInput());
break;
case R_UPDATE_PRICE:
updatePrice();
break;
case R_GENERATE_JSON_FROM_MAP:
res=generateJSONFromMap();
break;
}
System.out.println("FROM REPLICA, ACK FOR"+c.getSqnCommand());
this.setLastCmdReceived(c.getSqnCommand());
sendAckToQueueFrontEnd(c.getSqnCommand(),res);
} catch (JMSException ex) {
Logger.getLogger(Replica1.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private void sendJMSMessageToQueueFrontEnd(String messageData) {
context.createProducer().send(queueFrontEnd, messageData);
}
private void sendAckToQueueFrontEnd(long sqn_command,Object responce) {
try {
ResponceMessage ack=new ResponceMessage(true,false,sqn_command,COD_REPLICA);
ack.setResponce(responce);
ObjectMessage objectMessage=context.createObjectMessage();
objectMessage.setObject(ack);
context.createProducer().send(queueFrontEnd,objectMessage);
} catch (JMSException ex) {
Logger.getLogger(Replica1.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
前端代码:
(doOperation 在我的代码中与 sendNewCommand() 映射)
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package EJBData;
import EJBExecutor.ReaderLocal;
import Service.Command;
import Service.Product;
import Service.ResponceMessage;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerConfig;
import javax.ejb.TimerService;
import javax.inject.Inject;
import javax.jms.JMSConnectionFactory;
import javax.jms.JMSContext;
import javax.jms.JMSException;
import javax.jms.ObjectMessage;
import javax.jms.Topic;
/**
*
* @author melix
*/
@Stateless
public class AuctionFrontEnd implements AuctionFrontEndLocal{
@EJB
private FrontEndConsumer frontEndConsumer;
@EJB
private ReaderLocal reader;
@Resource(mappedName = "TopicRepliche")
private Topic topicRepliche;
@Inject
@JMSConnectionFactory("java:comp/DefaultJMSConnectionFactory")
private JMSContext context;
@Resource
TimerService service;
private boolean isConsumerInit=false;
private final int R_CONTAINS_KEY=0;
private final int W_REMOVE_KEY=1;
private final int W_PUT=2;
private final int R_GET=3;
private final int R_UPDATE_PRICE=4;
private final int R_GENERATE_JSON_FROM_MAP=5;
private final ConcurrentHashMap<Integer,Product> item_map=new ConcurrentHashMap<>();
private ArrayList<ConcurrentHashMap<Long,ResponceMessage>> listOfHashMap;
private Queue<Command> pending_command = new LinkedList<Command>();
private final int WRITE_QUORUM=2;
private final int READ_QUORUM=2;
private final int NUM_REPLIC=3;
private int last_key_inserted=0;
private long num_command=0;
public void initConsumer(){
frontEndConsumer.init();
}
private synchronized void putCommandInQueue(Command c){
pending_command.add(c);
}
private synchronized Command removeCommandFromQueue(Command c){
if(!pending_command.isEmpty())
return pending_command.remove();
return null;
}
private synchronized void addAck(int cod_replica,long num_command,ResponceMessage m){
listOfHashMap.get(cod_replica).put(num_command,m);
}
private synchronized void addResponce(int cod_replica,long num_command,ResponceMessage m){
listOfHashMap.get(cod_replica+3).put(num_command,m);
}
@Override
public synchronized void addAckToList(int cod_replica,long num_command,ResponceMessage m){
addAck(cod_replica,num_command,m);
}
@Override
public synchronized void addResponceToList(int cod_replica,long num_command,ResponceMessage m){
addAck(cod_replica,num_command,m);
}
private synchronized long addNumCommand(){
this.num_command++;
return num_command;
}
@Override
public void mexReceived(String message){
System.out.println(message);
}
@Timeout
public void handleTimeout(Timer timer) {
if(!pending_command.isEmpty()){
Command c=pending_command.poll();
for(int i=0;i<NUM_REPLIC*2;i++){
if(listOfHashMap.get(i).containsKey(c.getSqnCommand())){
ResponceMessage m=listOfHashMap.get(i).get(c.getSqnCommand());
System.out.println("Ack per comando:"+m.getSqnCommand()+"from replica"+m.getCode_replica());
}
}
}
timer.cancel();
}
public void startTimer() {
TimerConfig config = new TimerConfig();
config.setPersistent(false);
Timer timer = service.createSingleActionTimer(200, config);
}
private ResponceMessage[] sendNewCommand(boolean isWriteOperation,int type,Object input){
int num_ack=0,i=0;
Command c=new Command(isWriteOperation,addNumCommand(),type,input);
ObjectMessage objectMessage=context.createObjectMessage();
try {
objectMessage.setObject(c);
} catch (JMSException ex) {
Logger.getLogger(AuctionFrontEnd.class.getName()).log(Level.SEVERE, null, ex);
}
if(!isConsumerInit){
this.initConsumer();
isConsumerInit=true;
}
frontEndConsumer.cleanQueue();
sendJMSMessageToTopicRepliche(objectMessage);
ResponceMessage[] m=new ResponceMessage[NUM_REPLIC];
ResponceMessage tmp = null;
do{
tmp=frontEndConsumer.consume();
if(tmp!=null){
System.out.println("ACK CORRECT"+tmp.getSqnCommand()+";"+c.getSqnCommand());
if(tmp.getSqnCommand()==c.getSqnCommand()){
m[num_ack]=tmp;
num_ack++;
}
}
}while(tmp!=null);
System.out.println("sono alla fine!");
if(isWriteOperation&&num_ack>=WRITE_QUORUM)
return m;
if(!isWriteOperation&&num_ack>=READ_QUORUM)
return m;
return null;
}
@Override
public boolean containsKey(int key){
/*ResponceMessage[] m;
m=sendNewCommand(true,R_CONTAINS_KEY,key);
if(m!=null)
return (boolean)m[0].getResponce();
else
return false;*/
return item_map.containsKey(key);
}
@Override
public boolean removeKey(int key){
//ResponceMessage[] m;
//m=sendNewCommand(true,W_REMOVE_KEY,key);
item_map.remove(key);
return true;
/*if(m!=null)
return (boolean)m[0].getResponce();
else
return false;*/
}
@Override
public boolean put(Product b){
ResponceMessage[] m;
m=sendNewCommand(true,W_PUT,b);
item_map.put(Integer.parseInt(b.getId()),b);
last_key_inserted=Integer.parseInt(b.getId());
if(m!=null){
//last_key_inserted=Integer.parseInt(b.getId());
//return (boolean)m[0].getResponce();
if((boolean)m[0].getResponce())
System.out.println("V_TRUE");
else
System.out.println("FALSE");
}//else
// return false;
return true;
}
@Override
public Product get(int key){
//ResponceMessage[] m;
//m=sendNewCommand(true,R_GET,key);
return item_map.get(key);
/*if(m!=null)
return (Product)m[0].getResponce();
else
return null;*/
}
@Override
public int getLastKeyInserted(){
return last_key_inserted;
}
@Override
public void updatePrice(){
//ResponceMessage[] m;
//m=sendNewCommand(true,R_UPDATE_PRICE,null);
for (Map.Entry pairs : item_map.entrySet()) {
int key=(int)pairs.getKey();
Product p=(Product)pairs.getValue();
double price=p.getInitialPrice();
item_map.remove(key);
if(price>=5)
p.setInitialPrice(price-5);
else
p.setInitialPrice(0);
item_map.put(key, p);
}
}
@Override
public String generateJSONFromMap(){
//ResponceMessage[] m;
//m=sendNewCommand(true,R_GENERATE_JSON_FROM_MAP,null);
String json="[";
for (Map.Entry pairs : item_map.entrySet()) {
Product p=(Product)pairs.getValue();
json+=p.toString();
json+=",";
}
if(json.endsWith(","))
json = json.substring(0,json.length() - 1);
json+="]";
return json;
/* if(m!=null)
return (String)m[0].getResponce();
else
return null;*/
}
private void sendJMSMessageToTopicRepliche(String messageData) {
context.createProducer().send(topicRepliche, messageData);
}
private void sendJMSMessageToTopicRepliche(ObjectMessage messageData) {
context.createProducer().send(topicRepliche, messageData);
}
public AuctionFrontEnd(){
final ConcurrentHashMap<Long,ResponceMessage> responce_list=new ConcurrentHashMap<>();
this.listOfHashMap = new ArrayList<>();
for(int i=0;i<2*NUM_REPLIC;i++){
this.listOfHashMap.add(new ConcurrentHashMap<Long,ResponceMessage>());
}
}
}
前端消费者class:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package EJBData;
import Service.Command;
import Service.ResponceMessage;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.jms.ConnectionFactory;
import javax.jms.JMSConsumer;
import javax.jms.JMSContext;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
/**
*
* @author melix
*/
@Stateless
public class FrontEndConsumer {
@Resource(lookup = "jms/__defaultConnectionFactory")
private ConnectionFactory connectionFactory;
@Resource(lookup = "QueueFrontEnd")
private Queue queueFrontEnd;
private JMSContext context;
private JMSConsumer consumer;
public void init(){
context = connectionFactory.createContext();
consumer = context.createConsumer(queueFrontEnd);
}
public void cleanQueue(){
while(consumer.receive(1000)!=null){
System.out.println("CANCELLO");
}
}
public ResponceMessage consume(){
Message m = consumer.receive(1000);
if (m != null) {
if(m instanceof ObjectMessage){
try {
Object object = ((ObjectMessage)m).getObject();
ResponceMessage mex=(ResponceMessage)object;
System.out.println("RICEVO");
return (ResponceMessage)mex;
} catch (JMSException ex) {
Logger.getLogger(FrontEndConsumer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
return null;
}
}
onMessage() 方法不需要等待 doOperation() 完成。 JMS API 启用异步通信,并在 JMS 提供程序的线程上调用 onMessage()。
我正在尝试使用 Java EE 实现(练习)主动复制算法。
我遇到了一个意想不到的问题。
我有这个功能(伪代码):
public boolean doOperation() in the frontEnd EJB{
sendJMSMessageToTopic(); //publish new command to the replica
Thread.sleep(200);
readFromQueue(); //read Ack from replica
control if write quorum is reached
commit or abort
return state (success or not)
}
问题是:
回调 onMessage() 已调用,但在 doOperation 的同一次调用中未收到响应。 当我再次调用 doOperation 时,我读取了先前调用 doOperation 方法的响应。
我使用 glassfish,并将所有组件部署在同一个应用程序服务器中。 我使用主题将请求发布到副本,并使用队列接收来自副本的响应。 FrontEnd 是 Singleton,Replicas 是 Message Drive Bean。
更新:我
我的副本代码
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package EJBData;
import Service.ResponceMessage;
import Service.Command;
import Service.Product;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.inject.Inject;
import javax.jms.JMSConnectionFactory;
import javax.jms.JMSContext;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
/**
*
* @author melix
*/
@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"),
@ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "TopicRepliche"),
//@ActivationConfigProperty(propertyName = "subscriptionDurability", propertyValue = "durable"),
@ActivationConfigProperty(propertyName = "clientId", propertyValue = "TopicRepliche"),
@ActivationConfigProperty(propertyName = "subscriptionName", propertyValue = "TopicRepliche")
})
public class Replica1 implements MessageListener {
@Resource(mappedName = "QueueFrontEnd")
private Queue queueFrontEnd;
@Inject
@JMSConnectionFactory("java:comp/DefaultJMSConnectionFactory")
private JMSContext context;
private final int R_CONTAINS_KEY=0;
private final int W_REMOVE_KEY=1;
private final int W_PUT=2;
private final int R_GET=3;
private final int R_UPDATE_PRICE=4;
private final int R_GENERATE_JSON_FROM_MAP=5;
private final int COD_REPLICA=0;
private final ConcurrentHashMap<Integer,Product> item_map=new ConcurrentHashMap<>();
private final ConcurrentHashMap<Long,Command> pending_command=new ConcurrentHashMap<>();
private long last_cmd_executed=0;
private long last_cmd_received=0;
private synchronized void setLastCmdExecuted(long last_cmd_executed){
this.last_cmd_executed=last_cmd_executed;
}
private synchronized void setLastCmdReceived(long last_cmd_received){
this.last_cmd_received=last_cmd_received;
}
public boolean containsKey(int key){
return item_map.containsKey(key);
}
public boolean removeKey(int key){
item_map.remove(key);
return true;
}
public boolean put(Product b){
item_map.put(Integer.parseInt(b.getId()),b);
return true;
}
public Product get(int key){
return item_map.get(key);
}
public void updatePrice(){
for (Map.Entry pairs : item_map.entrySet()) {
int key=(int)pairs.getKey();
Product p=(Product)pairs.getValue();
double price=p.getInitialPrice();
item_map.remove(key);
System.out.println(price);
if(price>=5)
p.setInitialPrice(price-5);
else
p.setInitialPrice(0);
item_map.put(key, p);
}
}
public String generateJSONFromMap(){
String json="[";
for (Map.Entry pairs : item_map.entrySet()) {
Product p=(Product)pairs.getValue();
json+=p.toString();
json+=",";
}
if(json.endsWith(","))
json = json.substring(0,json.length() - 1);
json+="]";
return json;
}
public Replica1() {
}
@Override
public void onMessage(Message message) {
Command c;
if (message instanceof ObjectMessage) {
try {
Object object = ((ObjectMessage) message).getObject();
c=(Command)object;
int command_type=c.getType();
Object res=null;
switch(command_type){
case R_CONTAINS_KEY:
res=containsKey((int)c.getInput());
break;
case W_REMOVE_KEY:
res=removeKey((int)c.getInput());
break;
case W_PUT:
res=put((Product)c.getInput());
break;
case R_GET:
res=get((int)c.getInput());
break;
case R_UPDATE_PRICE:
updatePrice();
break;
case R_GENERATE_JSON_FROM_MAP:
res=generateJSONFromMap();
break;
}
System.out.println("FROM REPLICA, ACK FOR"+c.getSqnCommand());
this.setLastCmdReceived(c.getSqnCommand());
sendAckToQueueFrontEnd(c.getSqnCommand(),res);
} catch (JMSException ex) {
Logger.getLogger(Replica1.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private void sendJMSMessageToQueueFrontEnd(String messageData) {
context.createProducer().send(queueFrontEnd, messageData);
}
private void sendAckToQueueFrontEnd(long sqn_command,Object responce) {
try {
ResponceMessage ack=new ResponceMessage(true,false,sqn_command,COD_REPLICA);
ack.setResponce(responce);
ObjectMessage objectMessage=context.createObjectMessage();
objectMessage.setObject(ack);
context.createProducer().send(queueFrontEnd,objectMessage);
} catch (JMSException ex) {
Logger.getLogger(Replica1.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
前端代码: (doOperation 在我的代码中与 sendNewCommand() 映射)
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package EJBData;
import EJBExecutor.ReaderLocal;
import Service.Command;
import Service.Product;
import Service.ResponceMessage;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerConfig;
import javax.ejb.TimerService;
import javax.inject.Inject;
import javax.jms.JMSConnectionFactory;
import javax.jms.JMSContext;
import javax.jms.JMSException;
import javax.jms.ObjectMessage;
import javax.jms.Topic;
/**
*
* @author melix
*/
@Stateless
public class AuctionFrontEnd implements AuctionFrontEndLocal{
@EJB
private FrontEndConsumer frontEndConsumer;
@EJB
private ReaderLocal reader;
@Resource(mappedName = "TopicRepliche")
private Topic topicRepliche;
@Inject
@JMSConnectionFactory("java:comp/DefaultJMSConnectionFactory")
private JMSContext context;
@Resource
TimerService service;
private boolean isConsumerInit=false;
private final int R_CONTAINS_KEY=0;
private final int W_REMOVE_KEY=1;
private final int W_PUT=2;
private final int R_GET=3;
private final int R_UPDATE_PRICE=4;
private final int R_GENERATE_JSON_FROM_MAP=5;
private final ConcurrentHashMap<Integer,Product> item_map=new ConcurrentHashMap<>();
private ArrayList<ConcurrentHashMap<Long,ResponceMessage>> listOfHashMap;
private Queue<Command> pending_command = new LinkedList<Command>();
private final int WRITE_QUORUM=2;
private final int READ_QUORUM=2;
private final int NUM_REPLIC=3;
private int last_key_inserted=0;
private long num_command=0;
public void initConsumer(){
frontEndConsumer.init();
}
private synchronized void putCommandInQueue(Command c){
pending_command.add(c);
}
private synchronized Command removeCommandFromQueue(Command c){
if(!pending_command.isEmpty())
return pending_command.remove();
return null;
}
private synchronized void addAck(int cod_replica,long num_command,ResponceMessage m){
listOfHashMap.get(cod_replica).put(num_command,m);
}
private synchronized void addResponce(int cod_replica,long num_command,ResponceMessage m){
listOfHashMap.get(cod_replica+3).put(num_command,m);
}
@Override
public synchronized void addAckToList(int cod_replica,long num_command,ResponceMessage m){
addAck(cod_replica,num_command,m);
}
@Override
public synchronized void addResponceToList(int cod_replica,long num_command,ResponceMessage m){
addAck(cod_replica,num_command,m);
}
private synchronized long addNumCommand(){
this.num_command++;
return num_command;
}
@Override
public void mexReceived(String message){
System.out.println(message);
}
@Timeout
public void handleTimeout(Timer timer) {
if(!pending_command.isEmpty()){
Command c=pending_command.poll();
for(int i=0;i<NUM_REPLIC*2;i++){
if(listOfHashMap.get(i).containsKey(c.getSqnCommand())){
ResponceMessage m=listOfHashMap.get(i).get(c.getSqnCommand());
System.out.println("Ack per comando:"+m.getSqnCommand()+"from replica"+m.getCode_replica());
}
}
}
timer.cancel();
}
public void startTimer() {
TimerConfig config = new TimerConfig();
config.setPersistent(false);
Timer timer = service.createSingleActionTimer(200, config);
}
private ResponceMessage[] sendNewCommand(boolean isWriteOperation,int type,Object input){
int num_ack=0,i=0;
Command c=new Command(isWriteOperation,addNumCommand(),type,input);
ObjectMessage objectMessage=context.createObjectMessage();
try {
objectMessage.setObject(c);
} catch (JMSException ex) {
Logger.getLogger(AuctionFrontEnd.class.getName()).log(Level.SEVERE, null, ex);
}
if(!isConsumerInit){
this.initConsumer();
isConsumerInit=true;
}
frontEndConsumer.cleanQueue();
sendJMSMessageToTopicRepliche(objectMessage);
ResponceMessage[] m=new ResponceMessage[NUM_REPLIC];
ResponceMessage tmp = null;
do{
tmp=frontEndConsumer.consume();
if(tmp!=null){
System.out.println("ACK CORRECT"+tmp.getSqnCommand()+";"+c.getSqnCommand());
if(tmp.getSqnCommand()==c.getSqnCommand()){
m[num_ack]=tmp;
num_ack++;
}
}
}while(tmp!=null);
System.out.println("sono alla fine!");
if(isWriteOperation&&num_ack>=WRITE_QUORUM)
return m;
if(!isWriteOperation&&num_ack>=READ_QUORUM)
return m;
return null;
}
@Override
public boolean containsKey(int key){
/*ResponceMessage[] m;
m=sendNewCommand(true,R_CONTAINS_KEY,key);
if(m!=null)
return (boolean)m[0].getResponce();
else
return false;*/
return item_map.containsKey(key);
}
@Override
public boolean removeKey(int key){
//ResponceMessage[] m;
//m=sendNewCommand(true,W_REMOVE_KEY,key);
item_map.remove(key);
return true;
/*if(m!=null)
return (boolean)m[0].getResponce();
else
return false;*/
}
@Override
public boolean put(Product b){
ResponceMessage[] m;
m=sendNewCommand(true,W_PUT,b);
item_map.put(Integer.parseInt(b.getId()),b);
last_key_inserted=Integer.parseInt(b.getId());
if(m!=null){
//last_key_inserted=Integer.parseInt(b.getId());
//return (boolean)m[0].getResponce();
if((boolean)m[0].getResponce())
System.out.println("V_TRUE");
else
System.out.println("FALSE");
}//else
// return false;
return true;
}
@Override
public Product get(int key){
//ResponceMessage[] m;
//m=sendNewCommand(true,R_GET,key);
return item_map.get(key);
/*if(m!=null)
return (Product)m[0].getResponce();
else
return null;*/
}
@Override
public int getLastKeyInserted(){
return last_key_inserted;
}
@Override
public void updatePrice(){
//ResponceMessage[] m;
//m=sendNewCommand(true,R_UPDATE_PRICE,null);
for (Map.Entry pairs : item_map.entrySet()) {
int key=(int)pairs.getKey();
Product p=(Product)pairs.getValue();
double price=p.getInitialPrice();
item_map.remove(key);
if(price>=5)
p.setInitialPrice(price-5);
else
p.setInitialPrice(0);
item_map.put(key, p);
}
}
@Override
public String generateJSONFromMap(){
//ResponceMessage[] m;
//m=sendNewCommand(true,R_GENERATE_JSON_FROM_MAP,null);
String json="[";
for (Map.Entry pairs : item_map.entrySet()) {
Product p=(Product)pairs.getValue();
json+=p.toString();
json+=",";
}
if(json.endsWith(","))
json = json.substring(0,json.length() - 1);
json+="]";
return json;
/* if(m!=null)
return (String)m[0].getResponce();
else
return null;*/
}
private void sendJMSMessageToTopicRepliche(String messageData) {
context.createProducer().send(topicRepliche, messageData);
}
private void sendJMSMessageToTopicRepliche(ObjectMessage messageData) {
context.createProducer().send(topicRepliche, messageData);
}
public AuctionFrontEnd(){
final ConcurrentHashMap<Long,ResponceMessage> responce_list=new ConcurrentHashMap<>();
this.listOfHashMap = new ArrayList<>();
for(int i=0;i<2*NUM_REPLIC;i++){
this.listOfHashMap.add(new ConcurrentHashMap<Long,ResponceMessage>());
}
}
}
前端消费者class:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package EJBData;
import Service.Command;
import Service.ResponceMessage;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.jms.ConnectionFactory;
import javax.jms.JMSConsumer;
import javax.jms.JMSContext;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
/**
*
* @author melix
*/
@Stateless
public class FrontEndConsumer {
@Resource(lookup = "jms/__defaultConnectionFactory")
private ConnectionFactory connectionFactory;
@Resource(lookup = "QueueFrontEnd")
private Queue queueFrontEnd;
private JMSContext context;
private JMSConsumer consumer;
public void init(){
context = connectionFactory.createContext();
consumer = context.createConsumer(queueFrontEnd);
}
public void cleanQueue(){
while(consumer.receive(1000)!=null){
System.out.println("CANCELLO");
}
}
public ResponceMessage consume(){
Message m = consumer.receive(1000);
if (m != null) {
if(m instanceof ObjectMessage){
try {
Object object = ((ObjectMessage)m).getObject();
ResponceMessage mex=(ResponceMessage)object;
System.out.println("RICEVO");
return (ResponceMessage)mex;
} catch (JMSException ex) {
Logger.getLogger(FrontEndConsumer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
return null;
}
}
onMessage() 方法不需要等待 doOperation() 完成。 JMS API 启用异步通信,并在 JMS 提供程序的线程上调用 onMessage()。