我在让示例 EJB 程序工作时遇到问题。它来自“从新手到专业人士的 J2EE 1.4 入门”的第 11 章 该示例包括一个消息驱动 Bean,但我似乎无法让定时会话 Bean 工作。我在 GlassFish 3 中不断收到以下错误消息。
WARNING: Local Exception Stack:
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'BLOB, SCHEDULE, INTERVALDURATION, OWNERID, STATE, LASTEXPIRATIONRAW, PKHASHCODE,' at line 1
Error Code: 1064
Call: SELECT TIMERID, INITIALEXPIRATIONRAW, BLOB, SCHEDULE, INTERVALDURATION, OWNERID, STATE, LASTEXPIRATIONRAW, PKHASHCODE, CREATIONTIMERAW, CONTAINERID FROM EJB__TIMER__TBL WHERE (((CONTAINERID = ?) AND (OWNERID = ?)) AND (STATE = ?))
bind => [89237833827221504, server, 0]
Query: ReadAllQuery(name="findTimersByContainerAndOwnerAndState" referenceClass=TimerState sql="SELECT TIMERID, INITIALEXPIRATIONRAW, BLOB, SCHEDULE, INTERVALDURATION, OWNERID, STATE, LASTEXPIRATIONRAW, PKHASHCODE, CREATIONTIMERAW, CONTAINERID FROM EJB__TIMER__TBL WHERE (((CONTAINERID = ?) AND (OWNERID = ?)) AND (STATE = ?))")
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:333)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:687)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:530)
at org.eclipse.persistence.sessions.server.ServerSession.executeCall(ServerSession.java:529)
at
...
这是代码:
-- TimeIt.java --
package timer;
import java.rmi.RemoteException;
import javax.ejb.EJBObject;
public interface TimeIt extends EJBObject {
// the public business method on the timer bean
public void startTimer() throws RemoteException;
}
-- TimeItHome.java --
package timer;
import java.rmi.RemoteException;
import javax.ejb.EJBHome;
import javax.ejb.CreateException;
public interface TimeItHome extends EJBHome {
// the create method for the timer bean.
public TimeIt create() throws CreateException, RemoteException;
}
-- TimeItBean.java --
package timer;
import java.rmi.RemoteException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.ejb.EJBException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import javax.ejb.TimedObject;
import javax.ejb.Timer;
import javax.ejb.TimerService;
import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class TimeItBean implements SessionBean, TimedObject {
// save a reference to the context
private SessionContext context;
// public business method to start the timer
public void startTimer() {
TimerService timerService = context.getTimerService();
// after initial five seconds, then every ten seconds
Timer timer = timerService.createTimer(5000, 10000, "timer");
}
public void ejbCreate() {
}
// *** TimedObject interface
// timer ejb method - timer expires - send message to queue
@Override
public void ejbTimeout(Timer timer) {
QueueConnection connection = null;
try {
// Obtain a JNDI connection using the jndi.properties file
Context context = new InitialContext();
// Look up a JMS Connection Factory
QueueConnectionFactory connectionFactory = (QueueConnectionFactory) context.lookup("jms/ConnectionFactory");
// Create a JMS Connection
connection = connectionFactory.createQueueConnection();
// Create the JMS Session
boolean transacted = false;
int acknowledgeMode = Session.AUTO_ACKNOWLEDGE;
QueueSession session = connection.createQueueSession(transacted, acknowledgeMode);
// lookup the queue (destination)
Queue queue = (Queue) context.lookup("jms/Queue");
// Create a sender for the session to the queue
QueueSender sender = session.createSender(queue);
// Create the message - a string to print on the other side
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd 'at' HH:mm:ss.SSS");
// Create a text message
TextMessage textMessage = session.createTextMessage();
// set the text of the message
textMessage.setText("log entry, the time is: " + dateFormat.format(new Date()));
// send the message
sender.send(textMessage);
}
catch(NamingException naming) {
naming.printStackTrace();
}
catch(JMSException jms) {
jms.printStackTrace();
}
finally {
if (connection != null) {
try {
connection.close();
}
catch (JMSException jms) {
}
}
}
}
// *** SessionBean interface
@Override
public void ejbActivate() throws EJBException, RemoteException {
// TODO Auto-generated method stub
}
@Override
public void ejbPassivate() throws EJBException, RemoteException {
// TODO Auto-generated method stub
}
@Override
public void ejbRemove() throws EJBException, RemoteException {
// TODO Auto-generated method stub
}
@Override
public void setSessionContext(SessionContext context) throws EJBException, RemoteException {
this.context = context;
}
}
这是我的 ejb-jar.xml 文件:
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar
id="ejb-jar_ID"
version="2.1"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd">
<display-name>MDB-Timer</display-name>
<enterprise-beans>
<session>
<ejb-name>TimeItBean</ejb-name>
<home>timer.TimeItHome</home>
<remote>timer.TimeIt</remote>
<ejb-class>timer.TimeItBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>