Created Chatbot on OpenFire but getting error - java

I am trying to make chatbot plugin for openfire.But when i run plugin on openfire then i am getting below error:-
2016.10.28 18: 04: 21 org.jivesoftware.openfire.container.PluginManager - Error loading plugin: C: \Program Files(x86)\ Openfire\ plugins\ hospitalbot
java.lang.NoSuchMethodError: org.jivesoftware.openfire.XMPPServerInfo.getName() Ljava / lang / String;
at org.jivesoftware.openfire.botz.BotzConnection.login(BotzConnection.java: 319)
at org.jivesoftware.openfire.botz.BotzConnection.login(BotzConnection.java: 272)
at org.jivesoftware.openfire.plugin.ChatBot.initializePlugin(ChatBot.java: 75)
at org.jivesoftware.openfire.container.PluginManager.loadPlugin(PluginManager.java: 447)
at org.jivesoftware.openfire.container.PluginManager.access$300(PluginManager.java: 68)
at org.jivesoftware.openfire.container.PluginManager$PluginMonitor.run(PluginManager.java: 1037)
at org.jivesoftware.openfire.container.PluginManager.installPlugin(PluginManager.java: 176)
at org.jivesoftware.openfire.admin.plugin_002dadmin_jsp._jspService(plugin_002dadmin_jsp.java: 180)
I have copied this plugin from below link :-
https://community.igniterealtime.org/docs/DOC-1130
I am getting error in below file :-
package org.jivesoftware.openfire.botz;
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.jivesoftware.openfire.Connection;
import org.jivesoftware.openfire.SessionManager;
import org.jivesoftware.openfire.SessionPacketRouter;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.roster.Roster;
import org.jivesoftware.openfire.auth.AuthToken;
import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.jivesoftware.openfire.net.VirtualConnection;
import org.jivesoftware.openfire.session.ClientSession;
import org.jivesoftware.openfire.session.LocalClientSession;
import org.jivesoftware.openfire.spi.ConnectionConfiguration;
import org.jivesoftware.openfire.user.UserAlreadyExistsException;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.StringUtils;
import org.xmpp.packet.JID;
import org.xmpp.packet.Packet;
import org.xmpp.packet.StreamError;
/**
* The objective of BotzConnection class is to create a robot/bot application as
* an internal user of the main XMPP server. The class's login methods performs
* the necessary (virtual) connection to the server. The bot can login as an
* anonymous or a real user.
*
* <p>
* The class's object uses a BotzPacketReceiver object passed to it via one of
* it's constructors or via calls to
* {#link #setPacketReceiver(BotzPacketReceiver)} method to receive packets from
* other XMPP entities to the bot. The bot can reply to these packets with
* {#link #sendPacket(Packet)} method. Thus, a class that wants to handle bot
* packets must implement {#link BotzPacketReceiver} class.
*
* <p>
* Below is a sample parrot bot code snippet illustrating how to use
* BotzConnection and BotzPacketReceiver:
*
* <blockquote>
*
* <pre>
* *
* * BotzPacketReceiver packetReceiver = new BotzPacketReceiver() {
* * BotzConnection bot;
* * public void initialize(BotzConnection bot) { this.bot = bot; }
* * public void processIncoming(Packet packet) {
* * if (packet instanceof Message) {
* * packet.setTo(packet.getFrom());
* * bot.sendPacket(packet);
* * }
* * }
* * public void processIncomingRaw(String rawText) {};
* * public void terminate() {};
* * };
* *
* * BotzConnection bot = new BotzConnection(packetReceiver);
* * try {
* * bot.login("MyUsername");
* * Presence presence = new Presence();
* * presence.setStatus("Online");
* * bot.sendPacket(presence);
* * } catch (Exception e) {
* * }
* *
* </pre>
*
* </blockquote>
*
* #author Aznidin Zainuddin
* #see BotzPacketReceiver
*/
public class BotzConnection extends VirtualConnection {
/**
* The packet receiver object that will handle receiving of packets.
*/
private BotzPacketReceiver packetReceiver;
/**
* Holds the initialization state of the packet receiver.
*/
private boolean initPacketReceiver;
/**
* Holds the session for the bot.
*/
private LocalClientSession localClientSession;
private Roster roster;
private JID jid;
/**
* Creates a new instance of BotzConnection.
*/
public BotzConnection() {}
/**
* Creates a new instance of BotzConnection with the specified packet
* receiver.
*
* <p>
* When login is attempted with an instance created with this constructor,
* the packetReceiver traps incoming packets and texts as soon as the bot
* logs on.
*
* #param packetReceiver
* BotzConnection packetReceiver
*/
public BotzConnection(BotzPacketReceiver packetReceiver) {
this.packetReceiver = packetReceiver;
}
public LocalClientSession getLocalClientSession() {
return localClientSession;
}
public Roster getRoster() {
return roster;
}
/**
* The method will be implicitly called by the server when the bot's
* connection is (virtually) closed. The method terminates the packet
* receiver.
*/
#
Override
public void closeVirtualConnection() {
if (packetReceiver != null && initPacketReceiver) {
packetReceiver.terminate();
initPacketReceiver = false;
}
}
/**
* Calls to this method is made by the server to deliver packets to the bot.
* This method will in turn call
* {#link BotzPacketReceiver#processIncoming(Packet)} of the packet receiver
* associated with the bot.
*
* #param packet
* XMPP packet
* #throws UnauthorizedException
* When packets could not be delivered due to authorization
* problem.
*/
public void deliver(Packet packet) throws UnauthorizedException {
if (packetReceiver == null)
return;
packetReceiver.processIncoming(packet);
}
/**
* Calls to this method is made by the server to deliver raw text to the
* bot. This method will in turn call
* {#link BotzPacketReceiver#processIncomingRaw(String)} of the packet
* receiver associated with the bot.
*
* #param text
* The text string delivered to the bot.
*/
public void deliverRawText(String text) {
if (packetReceiver == null)
return;
packetReceiver.processIncomingRaw(text);
}
/*
* (non-Javadoc)
*
* #see org.jivesoftware.openfire.Connection#getAddress()
*/
//#Override
public byte[] getAddress() throws UnknownHostException {
return InetAddress.getLocalHost().getAddress();
}
/*
* (non-Javadoc)
*
* #see org.jivesoftware.openfire.Connection#getHostAddress()
*/
//#Override
public String getHostAddress() throws UnknownHostException {
return InetAddress.getLocalHost().getHostAddress();
}
/*
* (non-Javadoc)
*
* #see org.jivesoftware.openfire.Connection#getHostName()
*/
//#Override
public String getHostName() throws UnknownHostException {
return InetAddress.getLocalHost().getHostName();
}
/**
* Get the bot's packet receiver
*
* #return BotzPacketReceiver packetReceiver
*/
public BotzPacketReceiver getPacketReceiver() {
return packetReceiver;
}
/**
* Get the resource portion of the bot's JID.
*
* #return Resource portion of the bot's JID.
*/
public String getResource() {
if (localClientSession == null)
return null;
return localClientSession.getAddress().getResource();
}
/**
* Get the node's portion of the bot's JID.
*
* #return Node portion of the bot's JID.
*/
public String getUsername() {
if (localClientSession == null)
return null;
return localClientSession.getAddress().getNode();
}
/**
* Get the node's portion of the bot's JID.
*
* #return Node portion of the bot's JID.
*/
public JID getIdentity() {
if (localClientSession == null)
return null;
return localClientSession.getAddress();
}
/**
* Check whether the bot session is still active.
*
* #return <tt>true</tt> if the bot is still active, <tt>false</tt>
* otherwise.
*/
public boolean isLoggedOn() {
return !isClosed();
}
/**
* Login to the XMPP server as an anonymous user. This method creates a
* virtual connection to the XMPP server and establish a user session. If
* the packet receiver is already defined, initialize it.
*
* #throws BotzSessionAlreadyExistsException
* If the users session already exists.
*/
public void login() throws BotzSessionAlreadyExistsException {
if (isClosed())
throw new BotzSessionAlreadyExistsException();
localClientSession = (LocalClientSession) SessionManager.getInstance().getSession(jid);
localClientSession.setAnonymousAuth();
if (packetReceiver != null) {
packetReceiver.initialize(this);
initPacketReceiver = true;
}
return;
}
/**
* A convenient way to login. It uses the default "Botz" as the JID resource
* and auto create the user if it doesn't exist.
*
* #param username
* The username to login with.
* #throws BotzSessionAlreadyExistsException
* If the bot's session already exists.
* #throws UserNotFoundException
* If it fails to create the user.
*
* #see #login(String, String, boolean)
*/
public void login(String username)
throws BotzSessionAlreadyExistsException, UserNotFoundException {
login(username, "Botz", true);
}
/**
* A convenient way to login. It auto create the user if it doesn't exist.
*
* #param username
* The username to login with.
* #param resource
* The resource the user will bind to.
* #throws BotzSessionAlreadyExistsException
* If the bot's session already exists.
* #throws UserNotFoundException
* If it fails to create the user.
*
* #see #login(String, String, boolean)
*/
public void login(String username, String resource)
throws BotzSessionAlreadyExistsException, UserNotFoundException {
login(username, resource, true);
}
/**
* Login to the XMPP server and establish a non-anonymous user session using
* the given username and resource. When <tt>createIfNotExist</tt> is
* <tt>true</tt>, a new user with the username will be created and stored
* in the database if it does not exist. When <tt>false</tt>, and the
* user does not exist, the method will not attempt the login. Whenever
* there's an error, the bot will not login.
*
* #param username
* Username to login with.
* #param resource
* The resource the user will bind to.
* #param createIfNotExist
* When specified as <tt>true</tt>, a new user will be created
* and stored in the database if it does not exist.
* #throws BotzSessionAlreadyExistsException
* If the bot's session already exists.
* #throws UserNotFoundException
* If it fails to create the user.
*/
public void login(String username, String resource, boolean createIfNotExist)
throws BotzSessionAlreadyExistsException, UserNotFoundException {
if (isClosed())
throw new BotzSessionAlreadyExistsException();
jid = new JID(username.toLowerCase(), XMPPServer.getInstance().getServerInfo().getXMPPDomain(), resource);
ClientSession oldSession = XMPPServer.getInstance().getRoutingTable()
.getClientRoute(jid);
// Check for session conflict
if (oldSession != null) {
try {
oldSession.incrementConflictCount();
int conflictLimit = SessionManager.getInstance()
.getConflictKickLimit();
if (conflictLimit != SessionManager.NEVER_KICK) {
// Kick out the old connection that is conflicting with the
// new one
StreamError error = new StreamError(
StreamError.Condition.conflict);
oldSession.deliverRawText(error.toXML());
oldSession.close();
} else
throw new BotzSessionAlreadyExistsException();
} catch (Exception e) {
Log.error("Error during login", e);
}
}
if (!XMPPServer.getInstance().getUserManager().isRegisteredUser(
jid.getNode())) {
if (createIfNotExist) {
try {
// Bot doesn't care of whatever password it is.
XMPPServer.getInstance().getUserManager().createUser(
jid.getNode(), StringUtils.randomString(15), null,
null);
} catch (UserAlreadyExistsException e) {
// Ignore
}
} else {
throw new UserNotFoundException();
}
}
localClientSession = (LocalClientSession) SessionManager.getInstance().getSession(jid);
localClientSession.setAuthToken(new AuthToken(jid.getNode()), jid
.getResource());
if (packetReceiver != null) {
packetReceiver.initialize(this);
initPacketReceiver = true;
}
this.roster = XMPPServer.getInstance().getRosterManager().getRoster(username);
}
/**
* Logout the bot and destroy the active session. This method need not be
* called explicitly unless, for example, when callers need to refresh the
* assign a different username or resource (re-login).
*/
public void logout() {
close();
}
/**
* Send a packet out to an XMPP entity. The packet must be one of
* <message/>, <iq/> or <presence/>. Callers need not specify the
* <tt>from</tt> attribute inside the packet because it will be
* automatically inserted with/replaced by the bot's real JID.
*
* #param packet
* The packet to send.
*/
public void sendPacket(Packet packet) {
if (isClosed())
throw new IllegalStateException("No valid session");
SessionPacketRouter router = new SessionPacketRouter(localClientSession);
router.route(packet);
}
/**
* Assign a packet receiver ({#link BotzPacketReceiver}) object that will
* receive packets to the bot. The method can be called repeatedly if
* necessary to dynamically change different packet receivers during a
* login. If the previous packet receiver is in an initialized state during
* this call, it will be terminated; and the new packet receiver will be
* initialized.
*
* <p>
* If the previous packetReceiver is the same with the new one, this method
* will ignore the assignment.
*
* #param packetReceiver
* The packetReceiver object
*/
public void setPacketReceiver(BotzPacketReceiver packetReceiver) {
if (this.packetReceiver == packetReceiver)
return;
if (this.packetReceiver != null && initPacketReceiver) {
this.packetReceiver.terminate();
initPacketReceiver = false;
}
this.packetReceiver = packetReceiver;
if (!isClosed()) {
this.packetReceiver.initialize(this);
initPacketReceiver = true;
}
}
/**
* Calls to this method is made by the server to notify about server
* shutdown to the bot.
*/
public void systemShutdown() {
close();
}
#
Override
public ConnectionConfiguration getConfiguration() {
// TODO Auto-generated method stub
return null;
}
}
Can any one please help me out as i am newb in openfire.

I think bot has not been customized for newer versions as you can see in trailing last posts in that discussions that it doesn't work for anyone.But you can always use smack api to create your own bot.
Create a bot id.
Create a Java App and connect to Openfire using Smack
Use a business logic once you receive the chats and reply to the same.

Related

Spring-boot No thread-bound request found when throw exception on JMS queue listener

I am trying to consume an AWS queue using Spring boot with JMS, and I am having a problem throwing exceptions in my consumer method.
Every time I try to throw a custom exception in my consumer method, to log into an Aspect, the following message is returned:
errorCause=java.lang.IllegalStateException: No thread-bound request
found: Are you referring to request attributes outside of an actual
web request, or processing a request outside of the originally
receiving thread? If you are actually operating within a web request
and still receive this message, your code is probably running outside
of DispatcherServlet/DispatcherPortlet: In this case, use
RequestContextListener or RequestContextFilter to expose the current
request., errorMessage=Error listener queue,
date=2018-06-29T17:45:26.290, type=InvoiceRefuseConsumer]
I have already created a RequestContextListener bean but I did not succeed.
Could someone tell me what might be causing this error?
Here is my code:
Module 1 - Queue consumer
#Service
public class InvoiceRefuseConsumer extends AbstractQueue implements IQueueConsumer{
#Autowired
private InvoiceRefuseService invoiceRefuseService;
#JmsListener(destination = "${amazon.sqs.queue-to-be-consumed}")
#Override
public void listener(#Payload String message) throws ApplicationException {
try {
//Convert the payload received by the queue to the InvoiceFuseParam object
InvoiceRefuseParam param = convertToPojo(message, InvoiceRefuseParam.class);
// Set the type and reason of the refused invoice
param.setType(InvoiceRefuseType.INVOICE_TREATMENT.getId());
if(param.getReasonCode().equals(InvoiceRefuseTypeOperationType.TYPE_OPERATION_INSERT.getDesc())) {
// Persist data information
invoiceRefuseService.save(param);
} else if(param.getReasonCode().equals(InvoiceRefuseTypeOperationType.TYPE_OPERATION_DELETE.getDesc())) {
// Remove refused invoice
invoiceRefuseService.delete(param.getKeyAccess(), param.getType());
}
} catch(Exception e) {
throw new ApplicationException("Error listener queue", e);
}
}
}
Module 2 - Service operations
#Service
public class InvoiceRefuseService {
/**
* automatically initiates the InvoiceRefuseCrud
*/
#Autowired
private InvoiceRefuseCrud invoiceRefuseCrud;
/**
* automatically initiates the SupplierCrud
*/
#Autowired
private SupplierCrud supplierCrud;
/**
* automatically initiates the SequenceDao
*/
#Autowired
private SequenceDao sequenceDao;
/**
* automatically initiates the InvoiceRefuseDao
*/
#Autowired
private InvoiceRefuseDao invoiceRefuseDao;
/**
* automatically initiates the OrderConsumerService
*/
#Autowired
private OrderConsumerService orderConsumerService;
/**
* automatically initiates the InvoiceOrderService
*/
#Autowired
private InvoiceOrderService invoiceOrderService;
/**
* automatically initiates the BranchWarehouseTypeDao
*/
#Autowired
private BranchWarehouseTypeDao branchWarehouseTypeDao;
/**
* Method created to delete a invoice refuse
* #param key
* #param type
* #throws ApplicationException
*/
#Transactional
public void delete(String key, int type) throws ApplicationException {
try {
// Search for the refused invoices
List<InvoiceRefuseModel> lsInvoiceRefuseModel = invoiceRefuseCrud.findBykeyAccessAndType(key, type);
if(ApplicationUtils.isEmpty(lsInvoiceRefuseModel)){
throw new FieldValidationException(getKey("key.notfound"));
}
// Remove refused invoice and cascate with the the scheduling order
invoiceRefuseCrud.deleteAll(lsInvoiceRefuseModel);
} catch (Exception e) {
throw new ApplicationException(getKey("api.delete.error"), e);
}
}
/**
* Method created to save a new invoice refuse
* #param param
* #throws ApplicationException
*/
#OneTransaction
public void save(InvoiceRefuseParam param) throws ApplicationException {
try {
for (String orderNumber : param.getOrderNumbers()) {
// Verify if the invoice refused key already exists
Optional.ofNullable(invoiceRefuseCrud.findBykeyAccessAndType(param.getKeyAccess(), param.getType()))
.filter(invoiceRefuses -> invoiceRefuses.isEmpty())
.orElseThrow(() -> new ApplicationException(getKey("invoice.alread.exists")));
// Convert to model
InvoiceRefuseModel model = convertToSaveModel(param, orderNumber);
// Save data on database
InvoiceRefuseModel result = invoiceRefuseCrud.save(model);
// Associate new refused invoice with the scheduled order
associateInvoiceRefusedToSchedulingOrder(result);
}
} catch (Exception e) {
throw new ApplicationException(getKey("api.save.error"), e);
}
}
/**
* Method creates to associate a refused invoice to the scheduling order
* #param invoiceRefuseModel
* #throws ApplicationException
*/
public void associateInvoiceRefusedToSchedulingOrder(InvoiceRefuseModel invoiceRefuseModel) throws ApplicationException{
// Search for the scheduled order
List<InvoiceOrderModel> lsInvoiceOrderModel = invoiceOrderService.findByNuOrder(invoiceRefuseModel.getNuOrder());
for (InvoiceOrderModel orderModel : lsInvoiceOrderModel) {
// Verify if its a SAP order
boolean isOrderSap = Optional
.ofNullable(branchWarehouseTypeDao.findByIdBranch(orderModel.getNuReceiverPlant()))
.filter(branch -> branch.getNaLoadPoint() != null)
.isPresent();
if (isOrderSap) {
// Update the order status
invoiceOrderService.updateStatus(orderModel);
}
}
}
/**
* Method created to convert from param to model
* #param param
* #param orderNumber
* #return InvoiceRefuseModel
* #throws ApplicationException
*/
private InvoiceRefuseModel convertToSaveModel(InvoiceRefuseParam param, String orderNumber) throws ApplicationException{
OrderParam orderParam = new OrderParam();
orderParam.getLsOrdeNumber().add(orderNumber);
// Search for SAP orders
OrderDataPojo orderSap = Optional.ofNullable(orderConsumerService.findAll(orderParam))
.filter(ordersSap -> ordersSap.getOrders().size() > 0)
.orElseThrow(() -> new ApplicationException(getKey("ordersap.notfound")));
// Convert to model
InvoiceRefuseModel model = new InvoiceRefuseModel();
model.setNuOrder(orderNumber);
model.setCdCompany(BranchMatrixType.MATRIX.getCdCompany());
model.setDsMessage(param.getReasonDescription());
model.setDtIssue(param.getIssueDate());
model.setKeyAccess(param.getKeyAccess());
model.setNuGuid(param.getGuid());
model.setNuInvoice(param.getInvoiceNumber() + param.getInvoiceSerialNumber());
model.setTsCreation(new Date());
model.setNuInvoiceSerial(param.getInvoiceSerialNumber());
model.setNuIssuerPlant(orderSap.getOrders().stream().map(o -> o.getHeader().getIssuerPlant()).findFirst().get());
model.setNuReceiverPlant(orderSap.getOrders().stream().map(o -> o.getHeader().getReceiverPlant()).findFirst().get());
model.setType(param.getType());
model.setCdInvoiceRefuseMessage(param.getReasonCode());
// Passing these fields is required for refused invoices, but they are not received for notes in treatment
if(param.getType().equals(InvoiceRefuseType.INVOICE_REFUSED.getId())) {
model.setIsEnableReturn(BooleanType.getByBool(param.getIsEnableReturn()).getId());
model.setDtRefuse(param.getRefuseDate());
}
// Search for the issuing supplier
SupplierModel supplierModelIssuer = findSupplier(param.getDocumentIdIssuer());
model.setCdSupplierIssuer(supplierModelIssuer.getCdSupplier());
// Search for the receiver supplier
SupplierModel supplierModelReceiver = findSupplier(param.getDocumentIdIssuer());
model.setCdSupplierReceiver(supplierModelReceiver.getCdSupplier());
// Set the primary key
InvoiceRefuseModelId id = new InvoiceRefuseModelId();
id.setCdInvoiceRefuse(sequenceDao.nextIntValue(SequenceName.SQ_INVOICE_REFUSE));
model.setId(id);
return model;
}
/**
* Method created to search for a supplier
* #param documentId
* #return SupplierModel
* #throws ApplicationException
*/
private SupplierModel findSupplier(String documentId) throws ApplicationException{
// Search for the supplier
SupplierModel model = supplierCrud.findTop1ByNuDocumentIdAndCdCompany(documentId, BranchMatrixType.MATRIX.getCdCompany());
if(model == null){
throw new ApplicationException(getKey("supplier.notfound"));
}
return model;
}
/**
* Method created to find a refused invoice and return the result by page
* #param param
* #param pageable
* #return Page<InvoiceRefuseModel>
* #throws ApplicationException
*/
public Page<InvoiceRefuseModel> findRefuseInvoice(InvoiceRefuseFilterParam param, Pageable pageable) throws ApplicationException {
return invoiceRefuseDao.findRefuseInvoice(param, pageable);
}
/**
* Method created to find a refused invoice and return the result by list
* #param param
* #return List<InvoiceRefuseModel>
* #throws ApplicationException
*/
public List<InvoiceRefuseModel> findRefuseInvoice(InvoiceRefuseFilterParam param) throws ApplicationException {
return invoiceRefuseDao.findRefuseInvoice(param);
}
/**
* Method created to find a refused invoice by order number and return the result by list
* #param nuOrder
* #return List<InvoiceRefuseModel>
*/
public List<InvoiceRefuseModel> findByNuOrder(String nuOrder){
return invoiceRefuseDao.findByNuOrder(nuOrder);
}
}

Mac application menu for java program that also runs on windows

I am working on a program that will work on both Windows and Mac machines. I found this link that explains how to implement the application menu on a Mac. But since it uses mac specific classes for interfaces I am not sure how to write the class so it compiles in Windows as well.
I can recommend JavaFx. The interface will look like windows on windows and like mac on mac. You can use normal java for everything that works on every machine. In addition, the Jfx Scene builder can help you with designing the application.
I should have googled a little further. Found this class on a old google group. Just had to extend it to include Preferences.
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class OSXAdapter implements InvocationHandler {
private OSXQuitListener _quitListener;
private OSXAboutListener _aboutListener;
private OSXPreferenceListener _perferenceListener;
/**
* creates this adapter, only does stuff when we're on a mac, if it's unable to
* register the quit adapter, then we throw an exception.
*
* #throws ClassNotFoundException
* #throws SecurityException
* #throws NoSuchMethodException
* #throws IllegalArgumentException
* #throws IllegalAccessException
* #throws InvocationTargetException
*/
#SuppressWarnings({ "rawtypes", "unchecked" })
public OSXAdapter() throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
// get's the os name
String vers = System.getProperty("os.name").toLowerCase();
// only attempt to the do the following if we're on a mac
if (vers.indexOf("mac") != -1) {
Class quitHandlerClass = Class.forName("com.apple.mrj.MRJQuitHandler");
Class aboutHandlerClass = Class.forName("com.apple.mrj.MRJAboutHandler");
Class prefHandlerClass = Class.forName("com.apple.mrj.MRJPrefsHandler");
Class mrjapputilsClass = Class.forName("com.apple.mrj.MRJApplicationUtils");
Object methodHandler = Proxy.newProxyInstance(quitHandlerClass.getClassLoader(), new Class[] { quitHandlerClass, aboutHandlerClass, prefHandlerClass }, this);
Method appUtilsObj = mrjapputilsClass.getMethod("registerQuitHandler", new Class[] { quitHandlerClass });
appUtilsObj.invoke(null, new Object[] { methodHandler });
appUtilsObj = mrjapputilsClass.getMethod("registerAboutHandler", new Class[] { aboutHandlerClass });
appUtilsObj.invoke(null, new Object[] { methodHandler });
appUtilsObj = mrjapputilsClass.getMethod("registerPrefsHandler", new Class[] { prefHandlerClass });
appUtilsObj.invoke(null, new Object[] { methodHandler });
}
}
/**
* registers an about dialog. When the os x system fires the event which
* triggers an about class
*
* #param listener
*/
public void setAboutListener(OSXAboutListener listener) {
_aboutListener = listener;
}
/**
* registers an preference listener. When the os x fires the preference event this will be
* fired.
*
* #param listener
*/
public void setPerferenceListener(OSXPreferenceListener listener) {
_perferenceListener = listener;
}
/**
* register an quit listener. When the os x fires the quit event this will be
* fired.
*
* #param listener
*/
public void setQuitListener(OSXQuitListener listener) {
_quitListener = listener;
}
/**
* #see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
* java.lang.reflect.Method, java.lang.Object[])
*/
public Object invoke(Object proxy, Method meth, Object[] args) throws Throwable {
if (meth.getName().equals("handleQuit")) {
if (null != _quitListener) {
_quitListener.handleQuit();
}
} else if (meth.getName().equals("handleAbout")) {
if (null != _aboutListener) {
_aboutListener.handleAbout();
}
} else if (meth.getName().equals("handlePrefs")) {
if (null != _perferenceListener) {
_perferenceListener.handlePrefs();
}
}
return null;
}
/**
* listener which listens to the about event from the os x
* system
*
* #author Chris Shorrock
*/
public interface OSXAboutListener {
/**
* handles the about display event.
*/
public void handleAbout();
}
/**
* this listener is fired when the os x system quits
*
* #author Chris Shorrock
*/
public interface OSXQuitListener {
/**
* this method is called when os x tells this application
* to quit.
*/
public void handleQuit();
}
/**
* this listener is fired when the os x system fires preferences
*
* #author Chris Shorrock
*/
public interface OSXPreferenceListener {
/**
* this method is called when os x tells this application
* to open preferences.
*/
public void handlePrefs();
}
}

resultSet.next() returns false, even though table is populated

I have a few functions that help with retrieving the objects from the database.
public User getUser(int beamID) throws NoSuchUserException {
return userFromResultSet(getUserResultSet(beamID));
}
private ResultSet getUserResultSet(int beamID) {
try(Connection conn = dataSource.getConnection()) {
// queries.getUserByBeamID() returns "SELECT * FROM user WHERE beamID=?"
PreparedStatement stmt = conn.prepareStatement(queries.getUserByBeamID());
stmt.setInt(1, beamID);
System.out.println(stmt.toString());
return stmt.executeQuery();
} catch (SQLException e) {
e.printStackTrace();
throw new IllegalStateException();
}
}
private User userFromResultSet(ResultSet resultSet) {
try {
boolean next = resultSet.next(); // Debugger tells me this is false.
if (!next)
throw new NoSuchUserException();
User user = new User(this,
resultSet.getInt("beamID"),
resultSet.getString("name"),
resultSet.getInt("points"),
resultSet.getInt("time")
);
if (resultSet.next())
throw new IllegalStateException("Duplicate user entries exist - database integrity compromised!");
return user;
} catch (SQLException e) {
e.printStackTrace();
throw new IllegalStateException();
}
}
The strange thing is, I know the data does exist for two reasons:
My program tries to create the entry if it does not exist, but attempting that gives an error that the unique constraint isn't being followed.
Running the query in my SQLite DB browser works just fine:
I highly doubt that this is an issue with uncommitted data, as this is a file-based database, and opening that file with a text editor shows instances of the usernames in the data.
Look closely at what you are doing here:
try (Connection conn = dataSource.getConnection()) {
PreparedStatement stmt = conn.prepareStatement(queries.getUserByBeamID());
stmt.setInt(1, beamID);
System.out.println(stmt.toString());
return stmt.executeQuery();
} catch (SQLException e) {
e.printStackTrace();
throw new IllegalStateException();
}
I believe it is the contract of try-with-resources to guarantee closing the resource specified in the try clause, after the expression finishes executing. I believe that the result set is also being closed at the end of the try block, hence calling next() returns false, because nothing is there.
The way I would have written your code is to populate the User POJO inside the try block, and return a User object instead of returning a result set:
private User getUserResultSet(int beamID) {
User user = null;
try (Connection conn = dataSource.getConnection()) {
PreparedStatement stmt = conn.prepareStatement(queries.getUserByBeamID());
stmt.setInt(1, beamID);
ResultSet rs = stmt.executeQuery();
rs.next();
user = new User(this,
rs.getInt("beamID"),
rs.getString("name"),
rs.getInt("points"),
rs.getInt("time")
);
} catch (SQLException e) {
e.printStackTrace();
throw new IllegalStateException();
}
return user;
}
Now your separation of concerns is better than before. Should something go wrong with the connection, result set, etc., it is handled in the actual code which deals with those things. In the event of an exception or other error, a null user object would be returned, and you should update your code to handle this possibility.
While the accepted answer addresses the root cause of the problem the actual implementation has some issues.
Exceptions are swallowed
PreparedStatement should be closed independently of the Connection
ResultSet should be closed independently of the PreparedStatement or the Connection
It does not handle TYPE_FORWARD_ONLY ResultSets that throw on ResultSet.next() when they are empty
It does not check that the result is unique
It does not have proper logging
A more complete example is below:
package com.stackoverflow.questions.Q42327984;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Optional;
import javax.sql.DataSource;
import lombok.Value;
import lombok.extern.log4j.Log4j2;
#SuppressWarnings("javadoc")
public class Answer {
/**
* <p>
* We use lombok's {#link Log4j2} annotation to create a Log4j2 logger, avoid using {#link System#out},
* {#link System#err} or {#link Throwable#printStackTrace()}
* </p>
*
* #See Lombok's log api.
* #See Log4j2's install guide.
*/
#Log4j2
static class UserDao {
final DataSource dataSource;
final UserQueries queries;
public UserDao(final DataSource dataSource, final UserQueries queries) {
this.dataSource = dataSource;
this.queries = queries;
}
/**
* Find {#link User} by beam id.
* <p>
* In most systems not finding a User would not be an "exceptional" condition, we should return {#link Optional}
* instead of throwing an {#link Exception}
* </p>
* <p>
* 'get' is fine for bean like things, but 'find' is for queries
* </p>
* <p>
* We add "ByBeamId" so we can disambiguate between this method and other queries that might also find
* {#link User} by a int value.
* </p>
*
* #param beamID the beam ID
* #return the {#link Optional} {#link User}, null's are the "billion dollar mistake"
* #throws {#link NoSuchUserException} the no such user exception
*/
public Optional<User> findUserByBeamId(int beamID) throws NoSuchUserException {
log.debug("findUserByBeamId({})", beamID);
final String userByBeamID = this.queries.getUserByBeamID();
log.debug("findUserByBeamId({}) userByBeamID query: {}", beamID, userByBeamID);
try (final Connection conn = this.dataSource.getConnection();
final PreparedStatement stmt = conn.prepareStatement(userByBeamID)) {
stmt.setInt(1, beamID);
/*
* ResultSets should be closed properly also
*/
try (final ResultSet rs = stmt.executeQuery()) {
/*
* There are other ways to find if the ResultSet is empty but the method below is safe and
* can handle most implementations
*/
int resultSetType = rs.getType();
try {
boolean scrolledForwardToRow = rs.next();
if (!scrolledForwardToRow) {
return Optional.empty();
}
} catch (SQLException e) {
/*
* ResultSets of TYPE_FORWARD_ONLY can throw a SQLException on ResultSet.next() if the ResultSet
* is
* empty.
*/
if (ResultSet.TYPE_FORWARD_ONLY == resultSetType) {
log.debug(
"findUserByBeamId({}): initial rs.next() call failed but ResultSet is TYPE_FORWARD_ONLY so returning empty.",
userByBeamID, e);
return Optional.empty();
}
log.error("findUserByBeamId({}): initial rs.next() call failed, return empty.", userByBeamID,
e);
throw e;
}
/*
* User should not have a reference to its DAO, this is a recipe for trouble.
*
* In general User should be an interface and a static factory method or a builder should be used
* for construction.
* 'new' should be avoided as it tightly couples a specific implementation of User.
*
* User user = new User(this,
* rs.getInt("beamID"),
* rs.getString("name"),
* rs.getInt("points"),
* rs.getInt("time"));
*/
/*
* Assigning to local variables has a couple advantages:
* - It makes stepping through the debugger much easier.
* - When an exception occurs the line number in the stack trace will only contain one method.
*
* Note, that the performance impact of local variables is not significant in a method of this
* complexity with so many external calls.
*/
final int beamIDFromRs = rs.getInt("beamID");
final String name = rs.getString("name");
final int points = rs.getInt("points");
final int time = rs.getInt("time");
final User user = User.of(beamIDFromRs, name, points, time);
/*
* Before we return our result we need to make sure it was unique.
*
* There are other ways to find if the ResultSet has no more row but the method below is safe
* can handle most implementations.
*/
try {
boolean scrolledForward = rs.next();
if (!scrolledForward) {
return Optional.of(user);
}
} catch (SQLException se) {
/*
* ResultSets of TYPE_FORWARD_ONLY can throw a SQLException on ResultSet.next() if the ResultSet
* is
* empty.
*/
if (ResultSet.TYPE_FORWARD_ONLY == resultSetType) {
log.debug(
"findUserByBeamId({}): rs.next() call failed but ResultSet is TYPE_FORWARD_ONLY so returning user: {}.",
userByBeamID, user, se);
return Optional.of(user);
}
log.error("findUserByBeamId({}): rs.next() call failed.", userByBeamID, se);
throw se;
}
log.error("findUserByBeamId({}): results not unique.", userByBeamID);
throw new IllegalStateException("findUserByBeamId(" + beamID + ") results were not unique.");
}
} catch (SQLException se) {
log.error("findUserByBeamId({}): failed", userByBeamID, se);
throw new IllegalStateException("findUserByBeamId(" + beamID + ") failed", se);
}
}
/**
* Gets the user.
*
* #param beamID the beam ID
* #return the {#link User}
* #throws NoSuchUserException if the user does not exist.
* #deprecated use {#link #findUserByBeamId(int)}
*/
#Deprecated
public User getUser(final int beamID) throws NoSuchUserException {
return findUserByBeamId(beamID).orElseThrow(() -> new NoSuchUserException(beamID));
}
}
interface UserQueries {
String getUserByBeamID();
}
/**
* Use interfaces to avoid tight coupling
*/
interface User {
/**
* static factory method for creating User instances
*
* #param beamID the beam ID
* #param name the name
* #param points the points
* #param time the time
* #return the user
*/
static User of(final int beamID, final String name, final int points, final int time) {
return new DefaultUser(beamID, name, points, time);
}
/**
* Gets the beam ID.
*
* #return the beam ID
*/
int getBeamID();
/**
* Gets the name.
*
* #return the name
*/
String getName();
/**
* Gets the points.
*
* #return the points
*/
int getPoints();
/**
* Gets the time.
*
* #return the time
*/
int getTime();
}
/**
* <p>
* We use lombok's {#link Value} to create a final immutable object with an all args constuctor
* ({#link #DefaultUser(int, String, int, int)} and proper
* {#link #toString()}, {#link #equals(Object)} and {#link #hashCode()} methods
* </p>
*
* #See Lombok's value api.
*/
#Value
static class DefaultUser implements User {
final int beamID;
final String name;
final int points;
final int time;
}
/**
* The Class NoSuchUserException.
*/
#SuppressWarnings("serial")
public static class NoSuchUserException extends RuntimeException {
final int beamID;
public NoSuchUserException(int beamID) {
this.beamID = beamID;
}
/**
* Gets the beam ID.
*
* #return the beam ID
*/
public int getBeamID() {
return this.beamID;
}
}
}

Java - Pausing a thread pool when it is executing with a JButton

I have a pause mechanism for my events(Runnable) but I am not sure how to use/call it when I need it to be called.
In my class, I have a run method that submits an arraylist full of events to an executor. (see run() on GreenhouseControls). When the Events are submitted, Thread.sleep(eventTime); is called and afterwards the action() inside the event is called.
My program requirement needs a mechanism that pauses all the threads with a method(which will be called by a method when clicked) which can be resumed later on with another button.
Does anyone know how to implement this mechanism?
Here are the files:
GreenhouseControls.java
package control;
/**
* In this exercise we take a different design approach to GreenhouseControls
*
* Compiled/Tested using Eclipse Version: Luna Release (4.4.0)
* TME4 Folder is located in C:\COMP 308\
*/
import java.io.*;
import java.util.regex.*;
import java.util.logging.*;
import java.util.*;
import java.util.concurrent.*;
import java.lang.reflect.*;
import tme4.*;
/**
* GreenhouseControls consists of the Greenhouse's status and methods that
* control what actions will be performed inside the Greenhouse.
* #author Ray Masiclat
*
*/
public class GreenhouseControls extends Controller implements Serializable{
/**
* status is a Set of StatusPair objects which contains information about the
* GreenhouseControls' status. The Default States are initialized in the default constructor.
*/
private Set<StatusPair> status = new HashSet<StatusPair>();
private static String file = "src/error.log";
/**
* Default Constructor - initializes each state of the Greenhouse
*
*/
public GreenhouseControls(){
status.add(new StatusPair<String, Boolean>("light", false));
status.add(new StatusPair<String, Boolean>("water", false));
status.add(new StatusPair<String, Boolean>("fans", false));
status.add(new StatusPair<String, Boolean>("windowok", true));
status.add(new StatusPair<String, Boolean>("poweron", true));
status.add(new StatusPair<String, String>("thermostat", "Day"));
status.add(new StatusPair<String, Integer>("errorcode", 0));
status = Collections.synchronizedSet(status);
}
/**
* Prints out in the console how to use the program.
*/
public static void printUsage() {
System.out.println("Correct format: ");
System.out.println(" java GreenhouseControls -f <filename>, or");
System.out.println(" java GreenhouseControls -d dump.out");
}
/**
* Takes in an errorcode and returns the appropriate Fix that will fix the
* error that occured in the past.
* #param errorcode
* #return fix
*/
public Fixable getFixable(int errorcode){
Fixable fix = null;
switch(errorcode){
case 1:
fix = new FixWindow(this);
break;
case 2:
fix = new PowerOn(this);
break;
default:
System.out.println("No Error");
break;
}
return fix;
}
/**
* shutdown - method creates a Logger that creates an error log which consists of information about the
* reason of why the program was shut down. After logging the error information, it serializes
* the current state of the program in order for it to be fixed/restored in the future.
* #throws IOException
*/
public void shutdown() throws IOException{
System.err.println("System Shutting Down");
Logger logger = Logger.getLogger("ControllerException");
FileHandler fh;
try {
fh = new FileHandler("src/error.log");
logger.addHandler(fh);
SimpleFormatter formatter = new SimpleFormatter();
fh.setFormatter(formatter);
} catch (SecurityException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//Check for errorcode using getError method.
int checkError = this.getError();
if(checkError == 1){
logger.info("Window Malfunction");
} else if (checkError == 2){
logger.info("Power Outage");
} else {
logger.info("No Error");
}
/**
* Serialize the current state and output it onto the src/ directory as dump.out
*/
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("src/dump.out"));
out.writeObject(this);
out.writeObject(getEventList());
out.close();
System.exit(0);
}
/**
* getStatus - returns the status Set which consists of information about the current state of the program.
* #return status
*/
public Set<StatusPair> getStatus(){
return status;
}
/**
* getError - Assigns an integer which will be used when logging the error.
* The errorNum is retrieved using the status Set
* #return errorNum
*/
public int getError(){
int errorNum = 0;
//Iterate through the status Set
for(StatusPair sp : status){
//Check for the name "errorcode" and initializes errorNum from its status
if(sp.getName().equals("errorcode")){
errorNum = (int) sp.getStatus();
}
}
return errorNum;
}
/**
* getEventList - returns a List of Events in the program.
* #return eventList
*/
public List<Event> getEventList(){
return eventList;
}
/**
* Create a method in GreenhouseControls called setVariable to
* handle updating to this collection. Use the synchronization feature
* in java to ensure that two Event classes are not trying to add to
* the structure at the same time.
* s - represents the name of the status
* o - represents the status it is going to be replaced with
* #param s
* #param o
*/
public void setVariable(String s, Object o){
for(StatusPair sp : getStatus()){
if(sp.getName().equals(s))
{
sp.setStatus(o);
}
}
}
/**
* addStatus - Adds a new status in the status Set and it is used
* if the program cannot find a name in the status Set.
* #param name
* #param status
*/
public void addStatus(String name, Object status){
getStatus().add(new StatusPair<String, Object>(name,status));
}
/**
* run - creates a thread array which will be used to run Events from
* the text file. Then a for loop is created to fill up the thread
* array with Events on each index. Then the thread is started once
* an index is initialized. After an event is added in to the thread
* array it is removed from the events list.
*/
public void run(){
ExecutorService exec = Executors.newCachedThreadPool();
if(eventList.size() == 1){
exec.submit(eventList.get(0));
eventList.remove(eventList.get(0));
} else {
for(Event e : eventList){
exec.submit(e);
}
}
exec.shutdown();
/*while(eventList.size() > 0){
for(int i = 0; i < eventList.size(); i++){
exec.submit(eventList.get(i));
}
}*/
/*Thread[] threads = new Thread[eventList.size()];
while(eventList.size() > 0)
for(int i = 0; i < eventList.size(); i++){
threads[i] = new Thread(eventList.get(i));
threads[i].start();
eventList.remove(i);
}*/
}
} ///:~
Event.java
/**
* Make Event implements Runnable so that each type of event provides
* its own timing. Each event file should be a class of its own. Change
* the rest of the design to simplify this model.
*
* Assignment: TME4
* #author Ray Masiclat
* #studentid 3231308
* #date July 27, 2015
*
*
* Compiled/Tested using Eclipse Version: Luna Release (4.4.0)
* TME4 Folder is located in C:\COMP 308\
*/
package tme4;
import java.io.*;
import java.util.logging.FileHandler;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import gui.*;
import control.*;
/**
* Event class that implements Runnable and Serializable
* #author Ray Masiclat
*
*/
public abstract class Event implements Runnable, Serializable{
/**
* eventTime - represents time it takes for the program to wait and then
* call its action method.
*/
protected long eventTime;
protected GreenhouseControls gcontrol;
protected boolean suspended = false;
/**
* Event class constructor which is used to initialize the Event's eventTime and
* GreenhouseControls object which is used for the Event to have access to its status
* variables.
* #param gc
* #param eventTime
*/
public Event(GreenhouseControls gc,long eventTime){
this.eventTime = eventTime;
this.gcontrol = gc;
}
/**
* getTime - returns the event's eventTime initialized from the constructor.
* #return eventTime
*/
public long getTime(){
return eventTime;
}
/**
* setTime - sets the eventTime
*/
public void setTime(long eventTime){
this.eventTime = eventTime;
}
/**
* run - Event class' run method is called when the Event is added in to the Thread
* and then "started". This method puts the Thread to sleep for however long the
* eventTime is. Afterwards, once it is done, it tries to run the Event's action
* method. If the action method throws an error, it is caught by the try-catch
* block which calls the GreenhouseControls object's shutdown which outputs an error.log
* file and serializes the current state of the GreenhouseControls object to a dump.out file.
*/
public void run(){
try {
synchronized(this){
while(suspended){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Thread.sleep(eventTime);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
this.action();
} catch (ControllerException e) {
//Use shutdown to create error log
try {
gcontrol.shutdown();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
}
}
public void suspend(){
suspended = true;
}
public synchronized void resume(){
suspended = false;
notify();
}
/**
* abstract method used to call an Event's action method in the run method.
* #throws ControllerException
*/
public abstract void action() throws ControllerException;
} ///:~
(Pastebin: GreenhouseControls.java
and Event.java)
Something like this:
boolean stop = false;
You can use a suspending/stopping object, like so
public class Stopping {
public synchronized void checkStop() {
if (stopped) {
wait(); // wait until stop has been cleared
}
}
public synchronized void setStop(boolean val) {
stop = val;
if (val) {
notifyAll();
}
}
}
Create one of these and share it with all your threads, making sure to call checkStop() frequently. Alternatively, you could make the methods in this class static, and then your threads wouldn't need an object reference - they could just call Stopping.checkStop();

java calling method from another class

Disclaimer - this is for an assignment, I'm trying to figure out why my code is giving me an error.
Background:
So the assignment is basically to make edits to SimpleChat, a client-server framework for which the teacher has given us the code. I am trying to implement a chat console from the server side, and implement actions that begin with hashtags. So I have a "handleMessageFromServer" method in my server file (called "EchoServer"), and am trying to call it from the server console (aptly named "Server Console"). I'll put the relevant code below, and explain it:
I'll edit what I've put, I'll put the whole files with comments.
Below is the "EchoServer" file. The more important bits relevant to my question are the "handleMessageFromServer" method, which I am trying to call from the other file and pass in information, as well as the EchoServer constructor, which I am using in the other file to create an instance.
import java.io.*;
import ocsf.server.*;
import common.*;
/**
* This class overrides some of the methods in the abstract
* superclass in order to give more functionality to the server.
*
* #author Dr Timothy C. Lethbridge
* #author Dr Robert Laganière
* #author François Bélanger
* #author Paul Holden
* #version July 2000
*/
public class EchoServer extends AbstractServer
{
//Class variables *************************************************
/**
* The default port to listen on.
*/
final public static int DEFAULT_PORT = 5555;
//Constructors ****************************************************
/*
* An interface type variable, will allow the implementation of the
* Display method in the client.
*
*/
public ChatIF server;
/**
* Constructs an instance of the echo server.
*
* #param port The port number to connect on.
*/
public EchoServer(int port, ChatIF server)
{
super(port);
this.server = server;
}
//Instance methods ************************************************
/**
* This method handles any messages received from the client.
*
* #param msg The message received from the client.
* #param client The connection from which the message originated.
*/
public void handleMessageFromClient
(Object msg, ConnectionToClient client)
{
System.out.println("Message received: " + msg + " from " + client);
this.sendToAllClients(msg);
}
/**
* This method handles any messages received from the server console.
*
* #param msg The message received from the server.
* #param server The connection from which the message originated.
*/
public void handleMessageFromServer(String message)
{
if (message.charAt(0) == '#')
{
serverCommand(message);
}
else
{
server.display(message);
this.sendToAllClients("SERVER MSG> " + message);
}
}
/*This method allows us to run commands from the server console
*
*/
public void serverCommand(String command)
{
if (command.equalsIgnoreCase("quit")) System.exit(0); /////Shuts the system down
else if (command.equalsIgnoreCase("#stop")) stopListening(); ///Stops listening for connections
else if (command.equalsIgnoreCase("#close")) ///////closes all connections
{
try close();
catch(IOException ex) {
server.display("Could not close connection");
}
}
else if (command.toLowerCase().startsWith("#setport")) /////Sets port when not listening
{
if (!isListening() && getNumberOfClients() == 0)
{
//////If there are no connected clients, and
//////we're not listening for new ones, we can
////assume that the server is closed (close() has been
////called.
String portNum = command.substring(s.indexOf("<") + 1)
portNum = portnum.substring(0, s.indexOf(">"));
int num = Integer.parseInt(portNum);
setPort(num);
server.display("The server port has been changed to port" + getPort());
}
else
{
server.display("Port cannot be changed");
}
else if (command.equalsIgnoreCase("#start")) ///////starts listening for clients if not already
{
if (!isListening())
{
try listen();
catch (Exception ex)
{
server.display("Could not listen for clients!");
}
}
else
{
server.display("Already listening for clients");
}
}
else if (message.equalsIgnoreCase("#getport")) //////gets the port number
{
server.display("Current port: " + Integer.toString(getPort()));
}
}
}
/**
* This method overrides the one in the superclass. Called
* when the server starts listening for connections.
*/
protected void serverStarted()
{
System.out.println
("Server listening for connections on port " + getPort());
}
/**
* This method overrides the one in the superclass. Called
* when the server stops listening for connections.
*/
protected void serverStopped()
{
System.out.println
("Server has stopped listening for connections.");
}
//Class methods ***************************************************
/**
* This method is responsible for the creation of
* the server instance (there is no UI in this phase).
*
* #param args[0] The port number to listen on. Defaults to 5555
* if no argument is entered.
*/
public static void main(String[] args)
{
int port = 0; //Port to listen on
try
{
port = Integer.parseInt(args[0]); //Get port from command line
}
catch(Throwable t)
{
port = DEFAULT_PORT; //Set port to 5555
}
EchoServer sv = new EchoServer(port);
try
{
sv.listen(); //Start listening for connections
}
catch (Exception ex)
{
System.out.println("ERROR - Could not listen for clients!");
}
}
}
//End of EchoServer class
Below is the ServerConsole file, where I am creating an instance of the EchoServer class so that I may pass in information. The purpose of this file is to create an environment where the server side can send text for the SimpleChat application. The text then gets passed back to the EchoServer class, where it can be used for commands (all the commands begin with hashtags). I am currently getting an error in the "accept" method, when trying to call echoServer.handleMessageFromServer(message). The error is "The method handleMessageFromServer(String) is undefined for the type EchoServer".
import java.io.*;
import client.*;
import common.*;
/**
* This class constructs the UI for a chat client. It implements the
* chat interface in order to activate the display() method.
* Warning: Some of the code here is cloned in ServerConsole
*
* #author François Bélanger
* #author Dr Timothy C. Lethbridge
* #author Dr Robert Laganière
* #version July 2000
*/
public class ServerConsole implements ChatIF
{
//Class variables *************************************************
/**
* The default port to connect on.
*/
final public static int DEFAULT_PORT = 5555;
//Instance variables **********************************************
/**
* The instance of the server that created this ConsoleChat.
*/
//Constructors ****************************************************
EchoServer echoServer;
/**
* Constructs an instance of the ClientConsole UI.
*
* #param host The host to connect to.
* #param port The port to connect on.
*/
public ServerConsole(int port)
{
this.echoServer = new EchoServer(port);
}
//Instance methods ************************************************
/**
* This method waits for input from the console. Once it is
* received, it sends it to the client's message handler.
*/
public void accept()
{
try
{
BufferedReader fromConsole =
new BufferedReader(new InputStreamReader(System.in));
String message;
while (true)
{
message = fromConsole.readLine();
///////////////ADDED FOR E50B MA/ND
echoServer.handleMessageFromServer(message);
///////////////ADDED FOR E50B MA/ND
}
}
catch (Exception ex)
{
System.out.println
("Unexpected error while reading from console!");
}
}
/**
* This method overrides the method in the ChatIF interface. It
* displays a message onto the screen.
*
* #param message The string to be displayed.
*/
public void display(String message)
{
System.out.println(message);
}
//Class methods ***************************************************
/**
* This method is responsible for the creation of the Client UI.
*
* #param args[0] The host to connect to.
*/
public static void main(String[] args)
{
int port = 0; //The port number
try
{
String host = args[0];
}
catch(ArrayIndexOutOfBoundsException e)
{
String host = "localhost";
}
ServerConsole chat= new ServerConsole(DEFAULT_PORT);
chat.accept(); //Wait for console data
}
}
//End of ConsoleChat class
I think I might not be constructing the instance right, but any help is greatly appreciated guys!
Your echoserver class has the following contructor:
public EchoServer(int port, ChatIF server)
{
super(port);
this.server = server;
}
note it takes in two parameters.
your call to the EchoServer is however only injecting a port
this.echoServer = new EchoServer(port);
Without seeing all your code my guess would be that Echoserver extends some other Server class that does not have the method you want.

Categories

Resources