/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://oss.oracle.com/licenses/CDDL+GPL-1.1
* or LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.s1asdev.ejb.ejb30.hello.mdb2;
import javax.ejb.MessageDriven;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerService;
import javax.ejb.EJBException;
import javax.ejb.NoSuchEJBException;
import javax.ejb.EJB;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
import javax.ejb.MessageDrivenContext;
import javax.naming.InitialContext;
import javax.jms.MessageListener;
import javax.jms.Message;
import javax.jms.Queue;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueConnection;
import javax.jms.QueueSession;
import javax.jms.QueueSender;
import javax.jms.TextMessage;
import javax.jms.Session;
import javax.transaction.TransactionManager;
import javax.transaction.Status;
import javax.annotation.Resource;
import java.util.Collection;
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
@MessageDriven(messageListenerInterface=MessageListener.class)
public class MessageBean implements javax.ejb.MessageDrivenBean {
@EJB(name="hello1") private Hello1 hello1;
@EJB private Hello2 hello2;
boolean onMessageInterceptorCalled = false;
boolean timeoutInterceptorCalled = false;
@Resource javax.ejb.MessageDrivenContext ctx;
@Resource javax.ejb.TimerService injectedTimerService;
@Resource(name="jms/MyQueueConnectionFactory")
QueueConnectionFactory qcFactory;
// Values for these will be specified in the standard deployment descriptor
// and the values will be different than the defaults.
@Resource String stringValue1 = "undefined";
@Resource(name="intValue1") int intValue1 = 1;
@Resource(name="integerValue1") Integer integerValue1 = new Integer(1);
short sv1 = 1;
// Value specified in deployment descriptor so this should be called.
@Resource void setShortValue1(short s) {
sv1 = s;
}
// Values for these will not be specified in the standard deployment
// descriptor so their defaults should apply.
@Resource String stringValue2 = "undefined";
@Resource int intValue2 = 1;
@Resource Integer integerValue2 = new Integer(1);
// corresponding env-entry is specified in ejb-jar.xml,
// but there is no value so no injection should happen and
// the default value should be used.
int intValue3 = 3;
// No value specified in deployment descriptor so this should never be
// called.
@Resource(name="shortValue2") void setShortValue2(short s) {
throw new IllegalStateException("setShortValue1 param = " + s +
" shouldn't be called");
}
@Resource
private void setMDC(javax.ejb.MessageDrivenContext context) {
try {
context.getTimerService();
throw new RuntimeException("Should have gotten IllegalStateEx");
} catch(IllegalStateException ise) {
System.out.println("Successfully got exception when accessing " +
"context.getTimerService() in " +
"setContext method");
}
}
public void setMessageDrivenContext(javax.ejb.MessageDrivenContext mdc) {
System.out.println("In MDB:setMessageDrivenContext");
}
public void ejbCreate() {
System.out.println("In MDB:ejbCreate");
}
public void ejbRemove() {
System.out.println("In MDB:ejbRemove");
}
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public void onMessage(Message message) {
System.out.println("Got message!!!");
try {
if( !onMessageInterceptorCalled ) {
throw new Exception("Error : interceptor wasn't invoked");
}
if( intValue3 == 3 ) {
// Also make sure env-entry is not visible in component env
try {
ctx.lookup("someIntValue3");
throw new Exception("shouldn't have found someIntValue3");
} catch(IllegalArgumentException ise) {
System.out.println("Successfully verified that " +
"env-entry someIntValue3 is not " +
"visible in java:comp/env");
}
} else {
throw new Exception("wrong value for intValue3 = " +
intValue3);
}
if( stringValue1.equals("undefined") ||
(intValue1 == 1) || (integerValue1.intValue() == 1) ||
(sv1 == 1) ) {
throw new Exception("env-entry @Resource override error");
} else {
System.out.println("stringValue1 = " + stringValue1 +
" intValue1 = " + intValue1 +
" integerValue1 = " + integerValue1 +
" shortValue1 = " + sv1);
}
if( !stringValue2.equals("undefined") ||
(intValue2 != 1) || (integerValue2.intValue() != 1) ) {
throw new Exception("env-entry @Resource override error");
}
// Proprietary way to look up tx manager.
TransactionManager tm = (TransactionManager)
new InitialContext().lookup("java:appserver/TransactionManager");
// Use an implementation-specific check to ensure that there
// is no tx. A portable application couldn't make this check
// since the exact tx behavior for TX_NOT_SUPPORTED is not
// defined.
int txStatus = tm.getStatus();
if( txStatus == Status.STATUS_NO_TRANSACTION ) {
System.out.println("Successfully verified tx attr = " +
"TX_NOT_SUPPORTED in onMessage()");
} else {
throw new Exception("Invalid tx status for TX_NOT_SUPPORTED" +
" method " + txStatus);
}
System.out.println("Calling hello1 stateless bean");
hello1.hello("local ejb3.0 stateless");
System.out.println("Calling hello11 stateless bean");
// Get context through direct "java:comp/EJBContext" lookup
MessageDrivenContext ctx2 = (MessageDrivenContext)
new InitialContext().lookup("java:comp/EJBContext");
Hello1 hello11 = (Hello1) ctx2.lookup("hello1");
hello11.hello("local ejb3.0 stateless 2");
System.out.println("Calling hello2 stateful bean");
hello2.hello("local ejb3.0 stateful");
hello2.removeMethod();
try {
hello2.hello("this call should not go through");
throw new Exception("bean should have been removed " +
"after removeMethod()");
} catch(NoSuchEJBException e) {
System.out.println("Successfully caught EJBException after " +
" accessing removed SFSB");
}
System.out.println("creating timer");
TimerService timerService = (TimerService)
new InitialContext().lookup("java:comp/TimerService");
timerService.createTimer(7000, "created timer");
Collection timers = injectedTimerService.getTimers();
if( timers.size() != 1 ) {
throw new IllegalStateException("invalid timer count = " +
timers.size());
}
} catch(Exception e) {
e.printStackTrace();
}
}
@Timeout private void timeout(javax.ejb.Timer t) {
QueueConnection connection = null;
try {
System.out.println("In MessageBean. Got timeout callback");
if( HelloStatelessSuper.timeoutHappened ) {
System.out.println("Verified that stateless session bean " +
" timeout happened");
} else {
throw new Exception("Stateless session bean timeout " +
"never happened");
}
if( timeoutInterceptorCalled ) {
throw new Exception("Error : interceptor was invoked." +
"Interceptors should not apply to timeout"
+ "methods");
} else {
System.out.println("Interceptor was successfully ignored for "
+ "timeout method");
}
InitialContext ic = new InitialContext();
// Proprietary way to look up tx manager.
TransactionManager tm = (TransactionManager)
ic.lookup("java:appserver/TransactionManager");
// Use an implementation-specific check to ensure that there
// is no tx. A portable application couldn't make this check
// since the exact tx behavior for TX_NOT_SUPPORTED is not
// defined.
int txStatus = tm.getStatus();
if( txStatus == Status.STATUS_NO_TRANSACTION ) {
System.out.println("Successfully verified tx attr = " +
"TX_NOT_SUPPORTED in timeout method");
} else {
throw new Exception("Invalid tx status for TX_NOT_SUPPORTED" +
" method " + txStatus);
}
Queue queue = (Queue) ic.lookup("java:comp/env/jms/ClientQueue");
connection = qcFactory.createQueueConnection();
QueueSession session = connection.createQueueSession(false,
Session.AUTO_ACKNOWLEDGE);
QueueSender sender = session.createSender(queue);
TextMessage tmessage = session.createTextMessage();
tmessage.setText("mdb() invoked");
System.out.println("Sending message");
sender.send(tmessage);
System.out.println("message sent");
} catch(Exception e) {
e.printStackTrace();
} finally {
try {
if(connection != null) {
connection.close();
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
@AroundInvoke
public Object intercept(InvocationContext inv)
throws Exception
{
System.out.println("[mdb] Interceptor invoked...");
System.out.println("method = " + inv.getMethod());
System.out.println("params = " + inv.getParameters());
int i = 0;
for(Object o : inv.getParameters()) {
System.out.println("param" + i + " = " + o);
i++;
}
if( inv.getMethod().getName().equals("onMessage") ) {
onMessageInterceptorCalled = true;
} else if( inv.getMethod().getName().equals("timeout") ) {
// This shouldn't happen. Interceptors don't apply to timeout
// methods.
timeoutInterceptorCalled = true;
}
Object o = inv.proceed();
System.out.println("[mdb] Interceptor after proceed()...");
return o;
}
}