For school we made a Java application with RMI, there are 3 applications: Server, Client and Rekenaar.
The line where it goes wrong is the Line: "test = (Range[])m.getAllRange();", it gives an dispatchUncaughtException.
package rekenaar;
import server.Opdracht;
import java.rmi.Naming;
import java.util.logging.Level;
import java.util.logging.Logger;
import interfaces.*;
import java.rmi.RemoteException;
/**
*
* #author Windows
*/
public class Rekenaar implements Runnable{
private Range range;
private IRekenCoördinator coordinator;
private long[] priemgetallen;
private Opdracht op;
private Range[] test;
public Rekenaar()
{
try{
this.coordinator = null;
this.coordinator = (IRekenCoördinator) Naming.lookup("rmi://127.0.0.1:1099/RekenC");
this.priemgetallen = coordinator.getPriemgetallen();
this.op = null;
}catch(Exception ex){ex.printStackTrace();}
}
public void Bereken()
{
try{
long rangeOndergrens = (op.getGetal()/2000) * 2000;
range = new Range(priemgetallen, rangeOndergrens);
op.setRange(range);
op.setUitkomst(range.geefSemiPriem(op.getGetal()));
coordinator.RemoveID(op.CheckRange());
IMagazijn m = op.getMagazijn();
test = (Range[])m.getAllRange();
String hoi = m.hoi();
m.AddRange(op);
}catch(RemoteException ex){ex.printStackTrace();}
}
#Override
public void run() {
KrijgtOpdracht();
}
private void KrijgtOpdracht()
{
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
Logger.getLogger(Rekenaar.class.getName()).log(Level.SEVERE, null, ex);
}
if(coordinator != null)
{
try{
op = (Opdracht)coordinator.getOpdracht();
}
catch (Exception ex)
{
ex.printStackTrace();
}
if(op != null ) this.Bereken();
this.run();
}
}
}
Interface:
package interfaces;
import java.io.IOException;
import java.rmi.Remote;
import java.rmi.RemoteException;
/**
*
* #author Windows
*/
public interface IMagazijn extends Remote {
/**
*
* #param op Uitgerekende opdracht waarvan de gegevens verwerkt moeten worden op de server
* #throws IOException
*/
public String hoi() throws RemoteException;
public IRange[] getAllRange() throws RemoteException;
public void AddRange(IOpdracht op) throws RemoteException;
}
And here is the Magazijn itself which gives the IRange over RMI:
package server;
import java.rmi.RemoteException;
import java.util.ArrayList;
import interfaces.*;
import java.rmi.server.UnicastRemoteObject;
public class Magazijn extends UnicastRemoteObject implements IMagazijn{
private IRange[] ranges;
private long ondergrens;
public void setOndergrens(long ondergrens) {
this.ondergrens = ondergrens;
}
private long bovengrens;
public void setBovengrens(long bovengrens) {
this.bovengrens = bovengrens;
}
private transient MagazijnManager MM;
private transient ArrayList<Opdracht> dubbeleOpdrachten;
private transient RekenCoördinator RC;
private transient int MAGAZIJN_GROOTTE;
public Magazijn(long ondergrens, long bovengrens, MagazijnManager mm, RekenCoördinator RC)throws RemoteException
{
ranges = new IRange[(int)(bovengrens-ondergrens)/2000];
this.bovengrens = bovengrens;
this.ondergrens = ondergrens;
dubbeleOpdrachten = new ArrayList<Opdracht>();
this.MM = mm;
this.RC = RC;
MAGAZIJN_GROOTTE = (int)(bovengrens - ondergrens) + 1;
}
public void AddRange(IOpdracht op) throws RemoteException
{
ArrayList<IOpdracht> returnList = new ArrayList<IOpdracht>();
ranges[op.getRangeIndex()] = op.getRange();
returnList.add(op);
for(Opdracht o : dubbeleOpdrachten)
{
if(o.getRangeIndex() == op.getRangeIndex())
{
o.setRange(op.getRange());
o.setUitkomst(o.getRange().geefSemiPriem(o.getGetal()));
returnList.add(o);
}
}
MM.StuurOpdrachtenTerug(returnList);
}
public IRange[] getAllRange() throws RemoteException
{
return ranges;
}
public String hoi() throws RemoteException
{
return "poep";
}
public IRange getRange(int rangeIndex)
{
return ranges[rangeIndex];
}
public void StuurOpdracht(Opdracht op)
{
Opdracht o =null;
o = RC.AddOpdracht(op);
if(o!=null)
{
dubbeleOpdrachten.add(o);
}
}
public long getOndergrens()
{
return ondergrens;
}
public long getBovengrens()
{
return bovengrens;
}
public int getMagazijnGrootte()
{
return MAGAZIJN_GROOTTE;
}
}
The Rekenaar got the whole class "Range" so that is not the problem. The problem is something between the casting of IRange into Range. Range itself is Serializable and implements IRange.
The error I get: Exception in thread "main" java.lang.ClassCastException: [Linterfaces.IRange; cannot be cast to [Lrekenaar.Range;
When using RMI, you won't receive the same implementations you have on the server side. Instead you get a proxy class which will call your server. So you cannot cast your method.
Change test to a
IRange[] test
That should do it.
Related
Can someone tell me how to add an attachment using ProducerTemplate?
I have been searching but I can not find an answer to my case.
I am using Camen 2.1 and I have these three clases:
MailSender2.java
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;
import org.apache.camel.Exchange;
import org.apache.camel.ExchangePattern;
import org.apache.camel.ProducerTemplate;
public class MailSender2 extends TypeMail{
private static final ResourceBundle RES = ResourceBundle.getBundle("mail");
protected static final String MAIL_NOTIFICATION_ENDPOINT=RES.getString("mail.host.location").trim()+":"+RES.getString("mail.port").trim();
private Map<String, Object> header;
public MailSender2() {
this.header=new HashMap<>();
}
public void send(ProducerTemplate template) {
this.header.put("From", this.getT_from());
this.header.put("To", this.getT_to());
this.header.put("Subject", this.getT_subject());
this.header.put(Exchange.CONTENT_TYPE, "text/html; charset=UTF-8");
//this.getF_ficher() <-- I have here the file to attach
//this.getT_ficnon() <-- I have here the name ot the file
//this.getT_ficext() <-- I have here the extension ot the file
template.sendBodyAndHeaders(MAIL_NOTIFICATION_ENDPOINT, this.getT_mensaje(), header);
}
}
TypeMail.java:
public class TypeMail {
private String t_id;
private String t_from;
private String t_to;
private String t_subject;
private String t_mensaje;
private byte[] f_ficher;
private String t_ficnon;
private String t_ficext;
public String getT_id() {
return t_id;
}
public void setT_id(String t_id) {
this.t_id = t_id;
}
public String getT_from() {
return t_from;
}
public void setT_from(String t_from) {
this.t_from = t_from;
}
public String getT_to() {
return t_to;
}
public void setT_to(String t_to) {
this.t_to = t_to;
}
public String getT_subject() {
return t_subject;
}
public void setT_subject(String t_subject) {
this.t_subject = t_subject;
}
public String getT_mensaje() {
return t_mensaje;
}
public void setT_mensaje(String t_mensaje) {
this.t_mensaje = t_mensaje;
}
public byte[] getF_ficher() {
return f_ficher;
}
public void setF_ficher(byte[] f_ficher) {
this.f_ficher = f_ficher;
}
public String getT_ficnon() {
return t_ficnon;
}
public void setT_ficnon(String t_ficnon) {
this.t_ficnon = t_ficnon;
}
public String getT_ficext() {
return t_ficext;
}
public void setT_ficext(String t_ficext) {
this.t_ficext = t_ficext;
}
}
MailCommunicationTransformer.java:
import org.apache.camel.CamelContext;
import org.apache.camel.Exchange;
import org.apache.camel.ProducerTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ws.soap.client.SoapFaultClientException;
public class MailCommunicationTransformer {
MailSender2 mailSender = null;
static Logger logger = LoggerFactory.getLogger(MailCommunicationTransformer.class);
public MailCommunicationTransformer()
{
}
public MailLog transform(Object actualMessage, Exchange exchange, CamelContext context)
{
mailSender = exchange.getIn().getBody(MailSender2.class);
try {
MailSenderDAO mailSenderDAO = (MailSenderDAO)context.getRegistry().lookup("MailSenderDAO");
mailSenderDAO.validarInput(mailSender);
if (mailSender!=null) {
ProducerTemplate template=exchange.getContext().createProducerTemplate();
try {
mailSender.send(template);
}
catch (Throwable ex) {
ex.printStackTrace();
exchange.setProperty(Exchange.EXCEPTION_CAUGHT,ex);
}
}
}catch (MailException me) {
me.printStackTrace();
exchange.setProperty(Exchange.EXCEPTION_CAUGHT,me);
}
Throwable e = exchange.getProperty(Exchange.EXCEPTION_CAUGHT,
Throwable.class);
String response = "OK";
if (e != null) {
StringBuffer mensaje = new StringBuffer();
if (e instanceof SoapFaultClientException) {
mensaje.append("MAIL fault exception: CLIENT. ");
} else {
mensaje.append("MAIL fault exception: MAIL. ");
}
logger.info("MailCommunicationTransformer",e);
while (e != null) {
e.printStackTrace();
mensaje.append(e.getMessage());
e = e.getCause();
}
response = mensaje.toString();
}
MailLog log = new MailLog(mailSender, response); //, protocolo
return log;
}
}
In TypeMail I have the file in f_ficher, and the fileName (t_ficnon) and extension (t_ficext), but I can not find how to attach this file in MailSender2 before template.sendBodyAndHeaders(.....)
Any help would be very appreciated.
Regards.
Perhaps I don't fully understand your question, but the ProducerTemplate don't know about the message type.
You just send a body and perhaps also headers to an endpoint.
Therefore the body just needs to be a fully constructed MimeMessage object as documented in the Camel Mail docs.
You can simply construct the mail message with Java and then use the object with the ProducerTemplate (what you already do).
template.sendBodyAndHeaders("your-smtp-endpoint", yourMimeMessageInstance, yourHeaderMap);
Thanks for the answer!
But, finally, I could do it this way:
new class EmailProcessor.java
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.util.Objects;
import java.util.ResourceBundle;
import javax.activation.DataHandler;
import org.apache.camel.Exchange;
import org.apache.camel.Message;
import org.apache.camel.Processor;
import org.apache.commons.codec.binary.Base64;
public class EmailProcessor implements Processor {
// Atributos de la clase
private TypeMail typeMail;
public EmailProcessor(TypeMail typeMail) {
this.typeMail = typeMail;
}
#Override
public void process(Exchange exchange) throws Exception {
Message ms = exchange.getIn();
ms.setHeader("From", this.typeMail.getT_from());
ms.setHeader("To", this.typeMail.getT_to());
ms.setHeader("Subject", this.typeMail.getT_subject());
ms.setHeader(Exchange.CONTENT_TYPE, "text/html; charset=UTF-8");
ms.setBody("<p style='font-family: Calibri;'>" + this.typeMail.getT_mensaje() + "</p>");
if (this.typeMail.getF_ficher() != null) {
String mimeType = "application/pdf";
if ("zip".equals(typeMail.getT_ficext())) {
mimeType = "application/zip";
}
ms.addAttachment(typeMail.getT_ficnom() + "." + typeMail.getT_ficext(), new DataHandler(typeMail.getF_ficher(), mimeType));
}
}
}
MailSender.java:
import java.util.ResourceBundle;
import org.apache.camel.ExchangePattern;
import org.apache.camel.ProducerTemplate;
public class MailSender extends TypeMail{
private static final ResourceBundle RES = ResourceBundle.getBundle("mail");
protected static final String MAIL_NOTIFICATION_ENDPOINT=RES.getString("mail.host.location").trim()+":"+RES.getString("mail.port").trim();
public MailSender() {
}
public void send(ProducerTemplate template) {
template.send(MAIL_NOTIFICATION_ENDPOINT, ExchangePattern.InOnly, new EmailProcessor(this));
}
}
I am trying to mock getInstance() of a singleton class below to return a mocked class instead:
Base class (passo9() is the method to be mocked):
package br.com.bb.ids.robo.passo09;
import br.com.bb.ids.robo.passo09.dao.RoboSkipDao;
import br.com.bb.ids.robo.passo09.exceptions.RoboSkipDaoFindException;
import br.com.bb.ids.robo.passo09.exceptions.RoboSkipDaoMergeException;
import br.com.bb.ids.robo.passo09.models.RoboSkip;
import javax.enterprise.context.ApplicationScoped;
#ApplicationScoped
public class Motor {
private static Motor instance;
public static Motor getInstance() {
if (instance == null) {
instance = new Motor();
}
return instance;
}
private Motor() {}
/**
* Method to be mocked
*
* #return error code (0 if successful)
* #throws Exception any non expected exception
*/
public int passo9() throws Exception {
try {
System.out.println("Verifica o ponto onde o robô parou");
RoboSkipDao rsDao = RoboSkipDao.getInstance();
RoboSkip rs = rsDao.findByPasso(9);
int resultadoPasso = Integer.parseInt(rs.getValor());
rs.setValor(Integer.toString(resultadoPasso + 32768));
rsDao.merge(rs);
}
catch (RoboSkipDaoFindException e) {
System.out.println("Erro ao consultar registro em robo_skip, passo = 9.");
e.printStackTrace();
return 2;
}
catch (NumberFormatException e) {
System.out.println("Número do registro inválido em robo_skip, passo 9.");
e.printStackTrace();
return 3;
}
catch (RoboSkipDaoMergeException e) {
System.out.println("Erro ao atualizar registro em robo_skip, passo 9.");
e.printStackTrace();
return 8;
}
return 0;
}
}
The extended class to be called instead of Motor above:
package br.com.bb.ids.robo.passo09;
import io.quarkus.test.Mock;
import javax.enterprise.context.ApplicationScoped;
#Mock
#ApplicationScoped
public class MotorMock extends Motor {
public MotorMock(Motor m) {}
#Override
public int passo9() throws Exception {
System.out.println("passo9() mockado - return 0");
return 0;
}
}
The Quarkus main class (Motor.getInstance() should return MotorMock instead of Motor in my test below):
package br.com.bb.ids.robo.passo09;
import io.quarkus.runtime.Quarkus;
import io.quarkus.runtime.annotations.QuarkusMain;
#QuarkusMain
public class Main {
public static void main(String[] args) {
if (args.length != 1 || !args[0].matches("true|false")) {
System.err.println("Indicação em desenvolvimento (true/false) obrigatória.");
return;
}
boolean emDesenvolvimento = Boolean.parseBoolean(args[0]);
System.out.println("Iniciando aplicação...");
try {
Motor motor = Motor.getInstance();
motor.setEmDesenvolvimento(emDesenvolvimento);
int returnCode = motor.passo9();
System.out.println("Finalizando aplicação...");
Quarkus.asyncExit(returnCode);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
My test module:
package br.com.bb.ids.robo.passo09;
import io.quarkus.test.junit.QuarkusMock;
import io.quarkus.test.junit.QuarkusTest;
import javax.inject.Inject;
import org.junit.jupiter.api.Test;
#QuarkusTest
public class MainTest {
#Inject
Motor motor;
#Test
public void testMain() {
MotorMock mm = new MotorMock(Motor.getInstance());
Mockito.when(((Motor)mm).getInstance()).thenReturn(mm);
QuarkusMock.installMockForType(mm, Motor.class);
System.out.println("Testando Main.main(args)...");
String[] args = new String[1];
args[0] = "true";
Main.main(args);
System.out.println("Testes com Main.main(args) efetuados com sucesso.");
}
}
I want to call MotorMock.passo9() instead of Motor.passo9() inside my test case. How do I achieve this? If possible, share with code example.
I have a controller GGSNAcceptController.java:
package com.viettel.pcrf.controller;
import com.viettel.fw.Exception.LogicException;
import com.viettel.fw.dto.BaseMessage;
import com.viettel.fw.web.controller.BaseController;
import com.viettel.pcrf.common.Const;
import com.viettel.pcrf.dto.GgsnAcceptDTO;
import com.viettel.pcrf.webconfig.service.GgsnAcceptService;
import java.io.Serializable;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
#Component
#ManagedBean(name = "ggsnAcceptController")
#Scope("view")
public class GGSNAcceptController extends BaseController implements Serializable, BaseTableCTRL {
/**
* VARIABLES & GETTER/SETTER
*/
private GgsnAcceptDTO ggsnAccept;
private GgsnAcceptDTO selectedGgsnAccept;
private List<GgsnAcceptDTO> listGgsnAccept;
public GgsnAcceptDTO getGgsnAccept() {
return ggsnAccept;
}
public void setGgsnAccept(GgsnAcceptDTO ggsnAccept) {
this.ggsnAccept = ggsnAccept;
}
public GgsnAcceptDTO getSelectedGgsnAccept() {
return selectedGgsnAccept;
}
public void setSelectedGgsnAccept(GgsnAcceptDTO selectedGgsnAccept) {
this.selectedGgsnAccept = selectedGgsnAccept;
}
public List<GgsnAcceptDTO> getListGgsnAccept() {
return listGgsnAccept;
}
public void setListGgsnAccept(List<GgsnAcceptDTO> listGgsnAccept) {
this.listGgsnAccept = listGgsnAccept;
}
/**
* SERVICE
*
*/
#Autowired
private GgsnAcceptService ggsnAcceptServ;
/**
* INIT
*
*/
#PostConstruct
#Override
public void init() {
updateCtrl();
}
#Override
public void updateCtrl() {
clear();
System.out.println(ggsnAcceptServ == null);
listGgsnAccept = ggsnAcceptServ.findAll();
}
private String ggsnAcceptSelected;
#Override
public void updateDB() {
try {
if (ggsnAccept == null) {
throw new LogicException("nullSelected", "GGSN Config is not yet selected!");
}
if (formStatus == Const.BTN_ADD && ggsnAcceptServ.isExisted(ggsnAccept)) {
throw new LogicException("insertExisted", "GGSN Config existed!");
}
// if (systemCfgSelected != null && systemCfgSelected.equals(systemCfg.getSystemCfgName()) && langServ.isExisted(systemCfg)) {
// throw new LogicException("updateExisted", "GGSN Config is existed!");
// }
BaseMessage msg = ggsnAcceptServ.updateGgsn(ggsnAccept);
if (msg.isSuccess()) {
reportSuccess("msgInfo", "Success");
}
updateCtrl();
selectedGgsnAccept = (GgsnAcceptDTO) msg.getOutputObject();
} catch (LogicException ex) {
reportError("msgInfo", ex.getDescription());
} catch (Exception ex) {
logger.error(ex, ex);
}
}
#Override
public void deleteDB() {
try {
if (ggsnAccept == null) {
throw new LogicException("nullSelected", "GGSN Config is not selected yet!");
}
BaseMessage msg = ggsnAcceptServ.deleteGgsn(ggsnAccept);
if (msg.isSuccess()) {
reportSuccess("msgInfo", "msg.delete.success");
}
updateCtrl();
} catch (LogicException ex) {
reportError("msgInfo", ex.getDescription());
} catch (Exception ex) {
logger.error(ex, ex);
}
}
#Override
public void prepareAdd() {
ggsnAccept = new GgsnAcceptDTO();
selectedGgsnAccept = null;
}
#Override
public void prepareEdit() {
if (selectedGgsnAccept != null) {
ggsnAccept = selectedGgsnAccept;
}
}
#Override
public void prepareDelete() {
if (selectedGgsnAccept != null) {
ggsnAccept = selectedGgsnAccept;
}
}
#Override
public void clear() {
selectedGgsnAccept = null;
ggsnAccept = null;
}
#Override
public void onRowChangeListener() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
An interface GgsnAcceptService.java:
package com.viettel.pcrf.webconfig.service;
import com.viettel.fw.dto.BaseMessage;
import com.viettel.pcrf.dto.GgsnAcceptDTO;
import java.util.List;
public interface GgsnAcceptService {
public List<GgsnAcceptDTO> findAll();
public List<GgsnAcceptDTO> findAll(List filters);
public BaseMessage updateGgsn(GgsnAcceptDTO ggsn) throws Exception;
public BaseMessage deleteGgsn(GgsnAcceptDTO ggsn) throws Exception;
public boolean isExisted(GgsnAcceptDTO ggsn) throws Exception;
}
And a class implement above interface:
package com.viettel.pcrf.webconfig.service;
import com.viettel.fw.common.util.extjs.FilterRequest;
import com.viettel.fw.dto.BaseMessage;
import com.viettel.pcrf.webconfig.repo.GgsnAcceptRepository;
import com.viettel.pcrf.common.util.mapper.GgsnAcceptMapper;
import com.viettel.pcrf.dto.GgsnAcceptDTO;
import java.util.List;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.viettel.service.BaseServiceImpl;
import java.util.ArrayList;
#Service
public class GgsnAcceptServiceImpl extends BaseServiceImpl implements GgsnAcceptService {
private GgsnAcceptMapper mapper = new GgsnAcceptMapper();
#Autowired
private GgsnAcceptRepository repository;
public Logger logger = Logger.getLogger(GgsnAcceptService.class);
#Override
public List<GgsnAcceptDTO> findAll(List filters) {
return mapper.toDtoBean(repository.findAll(repository.toPredicate(filters)));
}
#Override
public List<GgsnAcceptDTO> findAll() {
return mapper.toDtoBean(repository.findAll());
}
#Override
public BaseMessage updateGgsn(GgsnAcceptDTO ggsn) throws Exception {
BaseMessage msg = new BaseMessage();
GgsnAcceptDTO newGgsn = mapper.toDtoBean(repository.saveAndFlush(mapper.toPersistenceBean(ggsn)));
msg.setOutputObject(newGgsn);
msg.setSuccess(true);
return msg;
}
#Override
public boolean isExisted(GgsnAcceptDTO ggsn) throws Exception {
List<FilterRequest> listReq = new ArrayList<>();
listReq.add(new FilterRequest("IP", ggsn.getIp()));
return repository.findOne(repository.toPredicate(listReq)) != null;
}
#Override
public BaseMessage deleteGgsn(GgsnAcceptDTO ggsn) throws Exception {
BaseMessage msg = new BaseMessage();
repository.delete(mapper.toPersistenceBean(ggsn));
msg.setSuccess(true);
return msg;
}
}
I got an null error when trying to access a page call controller. Is there anything wrong with my code ?
My property ggsnAcceptServ always null although i have already set autowired for it. I'm new in Spring, please help to explain why this property null. Any help would be great.
You have a problem mixing jsf and spring:
#Component
#ManagedBean(name = "ggsnAcceptController")
#Scope("view")
Your controller will be executed in jsf context not in spring context. Thats why autowiering not working.
I am trying to implement ( for exercise ) , with Java EE , the algorithm of active replication.
I encountered an unexpected problem.
I have this function (pseudo-code):
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)
}
The problem is:
The callback onMessage() is called but the response is not received in the same invocation of the doOperation.
When I call doOperation again I read the response of previous invocation of doOperation method.
I use glassfish, and i deploy all component in the same application server.
I use a topic for publish the request to the replicas and a queue to receive the responce from the replicas. FrontEnd is Singleton and Replicas are Message Drive Bean.
UPDATE: I
My Replica Code
/*
* 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);
}
}
}
The front end code:
(doOperation is mapped with sendNewCommand() in my code)
/*
* 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>());
}
}
}
The frontEndConsumer 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;
}
}
The onMessage() method shouldn't need to wait for doOperation() to finish. The JMS API enables asynchronous communication and onMessage() is called on the JMS provider's thread.
I cannot get the client to send a message to another client without going through the server. It is an obligatory school project that should be implemented like that. I would appreciate it if someone could help me.
Server Interface:
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.List;
public interface ChatServerInt extends Remote {
public abstract void register(ChatClientInt inClient) throws RemoteException;
public abstract ChatClientInt[] getClients() throws RemoteException;
public void disconnect(ChatClientInt client) throws RemoteException;
}
Server Implementation:
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class ChatServerImp extends UnicastRemoteObject implements ChatServerInt, Runnable {
private ChatClientInt[] clientList;
int counter = 0;
private ArrayList<String> connectedClients;
/**
* List of all registered remote clients.
*/
private List<ChatClientInt> clients = null;
/**
* Construct an instance of the chat server.
*/
public ChatServerImp() throws RemoteException {
// initialise the list of client objects.
clients = new ArrayList<ChatClientInt>();
connectedClients = new ArrayList<String>();
clientList = new ChatClientInt[16];
}
/**
* Register a chat client.
*/
public void register(ChatClientInt inClient) throws RemoteException {
// perform registration.
synchronized(clients)
{
clients.add(inClient);
clientList[counter++] = inClient;
inClient = new ChatClientImp();
for(int i = 0 ; i < clients.size();i++) {
System.out.println(inClient.getName()+ "has joined\n");
}
}
}
/**After registering, each client will request the list of connected users.
* Get a list of chat clients.
*/
public synchronized ChatClientInt[] getClients() throws RemoteException {
// generate and return the list
return clientList;
}
public void disconnect(ChatClientInt client) throws RemoteException {
for(int i = 0; i < clients.size(); i++) {
System.out.println(client.getName() + "" + "has joined \n");
}
clients.remove(client);
}
/**
* Generate a random subset. Based on an implementation of D. Knuth's
* #return
*/
private static <T> List<T> randomSample2(List<T> items, int m) {
Random rnd = new Random();
for(int i=0;i<items.size();i++){
int pos = i + rnd.nextInt(items.size() - i);
T tmp = items.get(pos);
items.set(pos, items.get(i));
items.set(i, tmp);
}
return items.subList(0, m);
}
/**
* Run the server's main thread. The server should periodically
* iterate through all registered clients to find out if they
* are still alive. Any dead clients will be removed from the
* client list.
*/
public void run() {
while(true) {
//System.out.println("waiting for client connection....\n");
// sleep for a while
try {
Thread.sleep(5000);
// iterate through all the clients we know. if we can't communicate with the client
// then eliminate it else if we can communicate with the client then do nothing.
for(int i =0; i < clients.size(); i++) {
try {
if(clients.get(i).getName()==null) {
clients.remove(clients.get(i).getName());
System.out.println("Disconnected clients:\n" + clients.get(i).getName());
}
}
catch (RemoteException e) {e.printStackTrace();}
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* Start the chat server.
* #param args
*/
public static void main(String[] args) throws Exception {
//ChatServerInt server;
try {
String serverName = "rmi://localhost/ChatServer";
// create an instance of the chat server
//server = (ChatServerImp) new ChatServerImp();
//Launch the registry - saves invoking it manually
java.rmi.registry.LocateRegistry.createRegistry(1099);
// register the instance with the RMIRegistry
Naming.rebind(serverName, new ChatServerImp());
//Naming.rebind(serverName, server);
// create the server thread and start it
//Thread t = new Thread(server).start();
System.out.println("Server running.....\n");
}
catch(RemoteException ex) {
System.out.println("Error binding the server to rmi");
}
}
}
Message Interface:
import java.util.HashSet;
public interface MessageInt {
/**
* Add a chat recipient to the list of receivers
* #param inClient
*/
public abstract void addRecipient(ChatClientInt inClient);
/**
* Get the set of clients that have seen this message
* #return
*/
public abstract HashSet<ChatClientInt> getRecipients();
/**
* Get the message content.
* #return
*/
public abstract String getContent();
/**
* Get an ID for a sender of the message
* #return
*/
public abstract String getSource();
}
Message Implementation:
import java.io.Serializable;
import java.util.HashSet;
public class MessageImp implements MessageInt, Serializable {
/**
*
*/
private static final long serialVersionUID = -2686034785384409672L;
HashSet<ChatClientInt> clientSet = new HashSet<ChatClientInt>();
String messageContent;
String messageSource;
public MessageImp(String inUser , String inMsg) {
messageSource = inUser;
messageContent = inMsg;
}
/**
* Add a chat recipient to the list of receivers
* #param inClient
*/
public void addRecipient(ChatClientInt inClient) {
synchronized(inClient) {
clientSet.add(inClient);
}
}
/**
* Get the set of clients that have seen this message
* #return
*/
public HashSet<ChatClientInt> getRecipients() {
return clientSet;
}
/**
* Get the message content.
* #return
*/
public String getContent() {
return messageContent;
}
/**
* Get an ID for a sender of the message
* #return
*/
public String getSource() {
return messageSource;
}
}
Client Interface:
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface ChatClientInt extends Remote {
/**
* Process a newly received message.
*
* #param inMessage
*/
public void processMessage(MessageInt inMessage)throws RemoteException;
/**
* Returns the name of the client.
*/
public String getName() throws RemoteException;
public boolean sendMessage(MessageInt inMessage) throws RemoteException;
}
Client Implementation:
import java.io.Serializable;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;
public class ChatClientImp extends UnicastRemoteObject implements ChatClientInt, Runnable {
/**
*
*/
private static final long serialVersionUID = 74130345076834009L;
private ArrayList <String> eventHistory = new ArrayList<String>();
private HashSet<ChatClientInt> clientSet = new HashSet<ChatClientInt>();
private List<ChatClientInt> clients;// = new ArrayList<ChatClientInt>();
ChatClientInt[] listFromServer = new ChatClientInt[4];
String clientName;
String strMessage;
MessageInt messageObj;
ChatServerInt serverObj;
public ChatClientImp() throws RemoteException {
super();
clients = new ArrayList<ChatClientInt>();
}
public void processMessage(MessageInt inMessage) throws RemoteException {
System.out.println("message:" + inMessage.getRecipients().toString() + inMessage.getSource() + inMessage.getContent() + "\n");
}
public String getName() throws RemoteException {
return clientName;
}
public synchronized boolean sendMessage(MessageInt inMessage) throws RemoteException {
boolean success = false;
for(int i = 0; i < clients.size(); i++) {
clients.get(i).processMessage(inMessage);
inMessage.addRecipient(clients.get(i));
success = true;
}
return success;
}
public void displayMessage(String displayName, String displayMsg) {
Iterator<ChatClientInt> it = clientSet.iterator();
while(it.hasNext()) {
System.out.println(displayName + displayMsg + "\n");
}
}
public void run() {
Scanner scanner = new Scanner(System.in);
String userName = "";
try {
this.serverObj =(ChatServerInt) new ChatServerImp();
} catch (RemoteException e) {
e.printStackTrace();
}
// Keep requesting until a name is submitted that is not already used.
// checking for the existence of a name and adding the name
// is done while locking the set of names.
System.out.println("Please Enter a username\n");
while(true) {
userName = scanner.nextLine();
if(userName==null) {
return;
}
clientName = userName;
try {
serverObj.register(ChatClientImp.this);
listFromServer = serverObj.getClients();
clientSet.add(this);
} catch (RemoteException e) {
e.printStackTrace();
}
System.out.println("Hi" + " " + clientName + " " + "enter your message\n");
String msg = scanner.nextLine();
if(msg.equals("exit")) {
try {
serverObj.disconnect(this);
System.exit(0);
}
catch (RemoteException e) {
e.printStackTrace();
}
}//end if
if((listFromServer.length) > 1) {
System.out.println("list from client is" + " " + listFromServer.length + "going to try to send message.....\n");
try {
this.messageObj = new MessageImp(userName, msg);
boolean result = this.sendMessage(messageObj);
if(result) {
System.out.print("sending result is:" + result + "\n");
} else {
System.out.println("sending was not successful\n");
}
} catch (RemoteException e1) {
System.out.println("Error tryiing to send message from the Run()\n");
}
} else {
System.out.println("There is no one else logged on\n");
}
}
}
public static void main(String[] args) throws RemoteException {
String serverUrl= "rmi://localhost/ChatServer";
try {
ChatServerInt server = (ChatServerInt)Naming.lookup(serverUrl);
Thread thread = new Thread(new ChatClientImp());
thread.start();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (NotBoundException e) {
e.printStackTrace();
}
}
}
The only way you can do that with RMI is if the clients are also RMI servers and send stubs to each other somehow.