I'm new to spring integration and I'm using the following code,
public class Main {
/**
* #param args
*/
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"trail03ApplicationContext.xml");
MessageChannel channel = applicationContext.getBean(
"helloMessageChannel", MessageChannel.class);
Message<String> message = MessageBuilder.withPayload("World").build();
channel.send(message);
}
}
I don't have any problems in the code but the jvm doesn't exit after sending the message. It still runs in the background. It was evident from the jvmvisual viewer. Is there are anything that needs to shut down. I'm using eclipse for testing the applications.
This is my application Context
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<channel id="helloMessageChannel">
</channel>
<gateway service-interface="trail03.api.MessageService" id="myGateway" default-request-channel="helloMessageChannel"/>
<service-activator input-channel="helloMessageChannel"
ref="helloMessageService" method="sayHello" />
<beans:bean id="helloMessageService" class="trail03.impl.MessageServiceImpl" />
Related
I have int-aws:sqs-message-driven-channel-adapter on which if I set the errorChannel, the downstream exceptions go there.
However, when I don't set an errorChannel, the exception does not get logged. It does not go to the errorChannel which is expected. Is there a way, that such exceptions at least get logged? Is there a default errorlogger which can simply log such errors?
UPDATE
Posting XML and DSL config as per the comments. The error is simulated in the persistence layer by setting null for a #NotBlank field on the ServiceObject.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-aws="http://www.springframework.org/schema/integration/aws"
xmlns:int-jpa="http://www.springframework.org/schema/integration/jpa"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/jpa https://www.springframework.org/schema/integration/jpa/spring-integration-jpa.xsd
http://www.springframework.org/schema/integration/aws https://www.springframework.org/schema/integration/aws/spring-integration-aws.xsd">
<int:channel id="serviceLogChannel">
<int:interceptors>
<int:wire-tap channel="loggingChannel"/>
</int:interceptors>
</int:channel>
<int-aws:sqs-message-driven-channel-adapter sqs="amazonSQS"
auto-startup="true"
channel="serviceLogChannel"
id="sqsMessageDrivenChannelAdapter"
queues="${app.queue-name}"
max-number-of-messages="10"
visibility-timeout="5"
wait-time-out="20"
error-channel="errorChannel"/>
<int:chain input-channel="serviceLogChannel">
<int:json-to-object-transformer type="ServiceObject"/>
<int-jpa:outbound-channel-adapter entity-class="ServiceObject"
persist-mode="PERSIST"
entity-manager-factory="entityManagerFactory">
<int-jpa:transactional/>
</int-jpa:outbound-channel-adapter>
</int:chain>
<int:logging-channel-adapter log-full-message="true"
logger-name="tapInbound"
id="loggingChannel"/>
<int:service-activator input-channel="errorChannel" expression="#reThrow.rethrow(payload)" order="100"/>
</beans>
The ReThrow service-activator:
#Component
public class ReThrow {
public void rethrow(Exception exception) throws Exception {
throw exception;
}
}
The DSL config for the same is :
#Configuration
public class IntegrationConfiguration {
#Bean
public MessageProducer createSqsMessageDrivenChannelAdapter(
AmazonSQSAsync amazonSQSAsync,
MessageChannel serviceChannel,
MessageChannel errorChannel,
#Value("${app.queue-name}") String queueName) {
SqsMessageDrivenChannelAdapter adapter =
new SqsMessageDrivenChannelAdapter(amazonSQSAsync, queueName);
adapter.setVisibilityTimeout(5);
adapter.setWaitTimeOut(20);
adapter.setAutoStartup(true);
adapter.setMaxNumberOfMessages(10);
adapter.setOutputChannel(serviceChannel);
adapter.setErrorChannel(errorChannel);
adapter.setMessageDeletionPolicy(SqsMessageDeletionPolicy.NO_REDRIVE);
return adapter;
}
#Bean
public IntegrationFlow messageProcessingFlow(
MessageChannel serviceChannel, EntityManagerFactory entityManagerFactory) {
return IntegrationFlows.from(serviceChannel)
.transform(Transformers.fromJson(ServiceObject.class))
.handle(
Jpa.outboundAdapter(entityManagerFactory)
.entityClass(ServiceObject.class)
.persistMode(PersistMode.PERSIST),
e -> e.transactional())
.get();
}
#Bean
public IntegrationFlow errorProcessingFlow(MessageChannel errorChannel) {
return IntegrationFlows.from(errorChannel)
.handle(
m -> {
throw (RuntimeException) m.getPayload();
})
.get();
}
#Bean
public MessageChannel serviceChannel() {
return MessageChannels.publishSubscribe().get();
}
}
The SqsMessageDrivenChannelAdapter is fully based on the SimpleMessageListenerContainerFactory from Spring Cloud AWS and that one just delegates to a listener we provide. Looking to the code there is just no any error handling. So, the best way to deal with it at the moment to explicitly set an error-channel="errorChannel" and it is going to be logged via default logger subscribed to that global errorChannel.
And yes: it is not expected to go to the errorChannel by default. I'm not sure that there is such an official claim in our docs. Probably better to think about it as "no error channel by default", so it is up to underlying protocol client to handle thrown errors. Since there is no one there, then we don't have choice unless set error channel explicitly.
My Spring Integration flow is defined in xml as per below (note that I have removed the opening/closing characters as the xml was not displaying correctly in my question):
<int-amqp:channel id="actionInstructionTransformed" message-driven="false"/>
<int-xml:unmarshalling-transformer
input-channel="actionInstructionXmlValid" output-channel="actionInstructionTransformed"
unmarshaller="actionInstructionMarshaller" />
I have got a poller defined with:
<int:poller id="customPoller" default="true" trigger="customPeriodicTrigger" task-executor="customTaskExecutor" max-messages-per-poll="${poller.maxMessagesPerPoll}" error-channel="drsGatewayPollerError" />
<int:transactional propagation="REQUIRED" read-only="true" transaction-manager="transactionManager" />
</int:poller>
In Java, I have got my consumer defined with:
#Transactional(propagation = Propagation.REQUIRED, readOnly = true, value = "transactionManager")
#ServiceActivator(inputChannel = "actionInstructionTransformed", poller = #Poller(value = "customPoller"),
adviceChain = "actionInstructionRetryAdvice")
public final void processInstruction(final ActionInstruction instruction)
From the documentation (http://docs.spring.io/autorepo/docs/spring-integration/4.0.2.RELEASE/reference/html/amqp.html), I understand that actionInstructionTransformed should be pollable as I have added message-driven="false".
When running my Spring Boot app, I am getting the exception: Caused by: java.lang.IllegalStateException: A '#Poller' should not be specified for Annotation-based endpoint, since 'actionInstructionTransformed' is a SubscribableChannel (not pollable).
I am using Spring Boot 1.4.4.RELEASE.
How can I force actionInstructionTransformed to be recognised as pollable?
Perhaps you are not importing the XML? In that case, the framework will create a DirectChannel for the service activator input channel.
This works fine for me...
#SpringBootApplication
#ImportResource("context.xml")
public class So42209741Application {
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext context = SpringApplication.run(So42209741Application.class, args);
context.getBean("pollable", MessageChannel.class).send(new GenericMessage<>("foo"));
Thread.sleep(10000);
context.close();
}
#ServiceActivator(inputChannel = "pollable", poller = #Poller(fixedDelay = "5000"))
public void foo(String in) {
System.out.println(in);
}
}
context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int-amqp="http://www.springframework.org/schema/integration/amqp"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration/amqp http://www.springframework.org/schema/integration/amqp/spring-integration-amqp.xsd">
<int-amqp:channel id="pollable" message-driven="false" />
</beans>
I need to write a simple HTTP client to make simple GET request and get JSON response using Spring integration.
Call fails with no message in exception: org.springframework.web.client.HttpServerErrorException: 500 Internal Server Error.
I tried debugging Spring code and did it successfully till I have source code, namely till
in the method AbstractMessageHandler.handleMessage(Message message)
abstract handleMessageInternal(Message message) has been called which threw
exception saying that request with
URL = http://example.com?q={q}&authKey={authKey}&rows={rows}&page={page}&filter={filter}
failed. URL looked exactly as I quoted, i.e. expressions have not been executed.
Payload in the message was always as it should be - instance if ZtInput with correct field values.
Could anyone give me an idea what to do?
Here is spring-integration-zt-context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-http="http://www.springframework.org/schema/integration/http"
xmlns:oxm="http://www.springframework.org/schema/oxm"
xsi:schemaLocation="http://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http-2.1.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd">
<int:channel id="InChannelZt"></int:channel>
<int:channel id="OutChannelZt"></int:channel>
<!-- Gateway Start -->
<int:gateway id="ZtGateway" default-request-timeout="5000" default-reply-timeout="5000"
default-request-channel="InChannelZt" service-interface="com.example.service.ZtService">
<int:method name="getResults" request-channel="InChannelZt" reply-channel="OutChannelZt" />
</int:gateway>
<int-http:outbound-gateway id="locationZtGateway"
request-channel="InChannelZt"
reply-channel="OutChannelZt"
url="${zt_url}?q={q}&authKey={authKey}&rows={rows}&page={page}&filter={filter}"
http-method="GET"
reply-timeout='5000'
expected-response-type="com.example.vo.ZtResponse">
<int-http:uri-variable name="q" expression="payload.getQ()"/>
<int-http:uri-variable name="authKey" expression="payload.getAuthKey()"/>
<int-http:uri-variable name="rows" expression="payload.getRows()"/>
<int-http:uri-variable name="page" expression="payload.getPage()"/>
<int-http:uri-variable name="filter" expression="payload.getFilter()"/>
</int-http:outbound-gateway>
and two classes mentioned in it:
import com.xxxx.vo.ZtInput;
import com.xxxx.vo.ZtResponse;
public interface ZtService {
ZtResponse getSearchResults(ZtInput ztInput);
}
Payload:
public class ZtInput {
private String q; //=pink
private String authKey = "baef7f8e39c53f852c8a14b7f6018b58";
private String rows="20";
private String page="1";
private String filter = "";
public ZtInputVO() {
}
public String getQ() {
return q;
}
public void setQ(String q) {
this.q = q;
}
public String getAuthKey() {
return authKey;
}
public void setAuthKey(String authKey) {
this.authKey = authKey;
}
public String getRows() {
return rows;
}
public void setRows(String rows) {
this.rows = rows;
}
public String getPage() {
return page;
}
public void setPage(String page) {
this.page = page;
}
public String getFilter() {
return filter;
}
public void setFilter(String filter) {
this.filter = filter;
}
}
The URI in the exception is the original (unexpanded URI); the expansion is performed into a different variable. (We should/will change that to log the expanded URI). But the bottom line is your server didn't like the expanded URI and returned a 500 internal server error.
You can use a network/tcp monitor (eclipse has one built in or you can use wireshark) to examine the actual URL sent to the server. You can also look at the server logs, if enabled.
Or, in the debugger, step down to line 415 (in the current source code - version 4.0.4) and examine realUri.
EDIT: The exception now includes the expanded URI (currently available in 4.0.5.BUILD-SNAPSHOT and 4.1.0.BUILD-SNAPSHOT).
I am getting this error:
org.xml.sax.SAXParseException: cvc-datatype-valid.1.2.1: 'duke duke' is not a valid value for 'NCName'.
I am using this spring-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
bean id="duke duke"
class="Juggler"/>
/beans>
My bean id's value has spaces in between.
This is my main class:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args)
{
ApplicationContext ctx=new ClassPathXmlApplicationContext("config/spring-config.xml");
Juggler jg=(Juggler)ctx.getBean("duke duke");
jg.perform();
}
}
However if I change the xsd in spring-config to spring-beans-3.1.xsd. I don't get this error. Why is it so??
I am trying to deploy an enterprise application EAR consisting of:
an EJB 3.1 module containing stateless session beans
a web module containing servlets
to Apache Geronimo V3.0 (packaged as a WebSphere Community 3.0.0.4 Server).
The beans are exposed through the #LocalBean annotation and injected into the servlets using the #EJB annotation.
Without any application security settings defined, everything works flawlessly. But, as soon as I define even the simplest security setup, injection fails with the message:
java.lang.IllegalArgumentException: Invalid method interface: LocalBean
javax.security.jacc.EJBMethodPermission$MethodSpec.checkMethodInterface(EJBMethodPermission.java:303)
javax.security.jacc.EJBMethodPermission$MethodSpec.(EJBMethodPermission.java:209)
javax.security.jacc.EJBMethodPermission.(EJBMethodPermission.java:90)
org.apache.geronimo.openejb.GeronimoSecurityService.isCallerAuthorized(GeronimoSecurityService.java:100)
org.apache.openejb.core.stateless.StatelessContainer.invoke(StatelessContainer.java:159)
org.apache.openejb.core.ivm.EjbObjectProxyHandler.synchronizedBusinessMethod(EjbObjectProxyHandler.java:255)
org.apache.openejb.core.ivm.EjbObjectProxyHandler.businessMethod(EjbObjectProxyHandler.java:235)
org.apache.openejb.core.ivm.EjbObjectProxyHandler._invoke(EjbObjectProxyHandler.java:92)
org.apache.openejb.core.ivm.BaseEjbProxyHandler.invoke(BaseEjbProxyHandler.java:284)
com.sun.proxy.$Proxy117.getSysTime(Unknown Source)
dk.danicon.servlet.Systime.doGet(Systime.java:43)
javax.servlet.http.HttpServlet.service(HttpServlet.java:575)
javax.servlet.http.HttpServlet.service(HttpServlet.java:668)
The security configuration works perfectly and prompts for credentials on servlets defined with an annotation like the one below, if they don't try to inject an EJB:
#ServletSecurity(#HttpConstraint(rolesAllowed={"admin"}))
I can make the injection work by removing the #LocalBean and implementing a #Local interface instead. But, from what I have been able to read on the subject, this should work with no-interface views as well - and I would like to avoid the added overhead from the interface.
I am attaching the relevant configuration files below and hope someone can tell me what I'm missing here?
application.xml (EAR module):
<?xml version="1.0" encoding="UTF-8"?>
<application id="Application_ID" version="6" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd">
<display-name>TestEar</display-name>
<module id="Module_1383740442312">
<web>
<web-uri>TestWeb.war</web-uri>
<context-root>test</context-root>
</web>
</module>
<module id="Module_1383741874882">
<ejb>TestEjb.jar</ejb>
</module>
</application>
geronimo-application.xml (EAR module):
<?xml version="1.0" encoding="UTF-8"?>
<app:application xmlns:app="http://geronimo.apache.org/xml/ns/j2ee/application-2.0" application-name="TestEar" xmlns:bp="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:client="http://geronimo.apache.org/xml/ns/j2ee/application-client-2.0" xmlns:conn="http://geronimo.apache.org/xml/ns/j2ee/connector-1.2" xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.2" xmlns:ejb="http://openejb.apache.org/xml/ns/openejb-jar-2.2" xmlns:jaspi="http://geronimo.apache.org/xml/ns/geronimo-jaspi" xmlns:log="http://geronimo.apache.org/xml/ns/loginconfig-2.0" xmlns:name="http://geronimo.apache.org/xml/ns/naming-1.2" xmlns:pers="http://java.sun.com/xml/ns/persistence" xmlns:pkgen="http://openejb.apache.org/xml/ns/pkgen-2.1" xmlns:sec="http://geronimo.apache.org/xml/ns/security-2.0" xmlns:web="http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1">
<dep:environment>
<dep:moduleId>
<dep:groupId>dk.danicon</dep:groupId>
<dep:artifactId>application</dep:artifactId>
<dep:version>1.0</dep:version>
<dep:type>car</dep:type>
</dep:moduleId>
<dep:dependencies>
<dep:dependency>
<dep:groupId>org.apache.geronimo.framework</dep:groupId>
<dep:artifactId>j2ee-security</dep:artifactId>
<dep:type>car</dep:type>
</dep:dependency>
<dep:dependency>
<dep:groupId>console.dbpool</dep:groupId>
<dep:artifactId>jdbc_ssodb</dep:artifactId>
<dep:version>1.0</dep:version>
<dep:type>car</dep:type>
</dep:dependency>
</dep:dependencies>
</dep:environment>
<sec:security>
<sec:role-mappings>
<sec:role role-name="admin">
<sec:principal class="org.apache.geronimo.security.realm.providers.GeronimoGroupPrincipal" name="ADMIN"/>
</sec:role>
</sec:role-mappings>
</sec:security>
<dep:gbean class="org.apache.geronimo.security.realm.GenericSecurityRealm" name="webrealm">
<dep:attribute name="realmName">webrealm</dep:attribute>
<dep:reference name="ServerInfo">
<dep:name>ServerInfo</dep:name>
</dep:reference>
<dep:xml-reference name="LoginModuleConfiguration">
<log:loginConfig>
<log:login-module control-flag="REQUIRED" wrap-principals="false">
<log:login-domain-name>webrealm</log:login-domain-name>
<log:login-module-class>org.apache.geronimo.security.realm.providers.SQLLoginModule</log:login-module-class>
<log:option name="dataSourceName">jdbc/ssodb</log:option>
<log:option name="userSelect">SELECT username, password FROM v4.app_users WHERE username = ?</log:option>
<log:option name="groupSelect">SELECT username, group_name FROM v4.app_users WHERE username = ?</log:option>
<log:option name="digest"/>
<log:option name="encoding"/>
</log:login-module>
</log:loginConfig>
</dep:xml-reference>
</dep:gbean>
</app:application>
ejb-jar.xml (EJB module):
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar version="3.1" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd">
<display-name>TestEjb </display-name>
</ejb-jar>
openejb-jar.xml (EJB module):
<?xml version="1.0" encoding="UTF-8"?>
<ejb:openejb-jar xmlns:ejb="http://openejb.apache.org/xml/ns/openejb-jar-2.2" xmlns:app="http://geronimo.apache.org/xml/ns/j2ee/application-2.0" xmlns:bp="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:client="http://geronimo.apache.org/xml/ns/j2ee/application-client-2.0" xmlns:conn="http://geronimo.apache.org/xml/ns/j2ee/connector-1.2" xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.2" xmlns:jaspi="http://geronimo.apache.org/xml/ns/geronimo-jaspi" xmlns:log="http://geronimo.apache.org/xml/ns/loginconfig-2.0" xmlns:name="http://geronimo.apache.org/xml/ns/naming-1.2" xmlns:pers="http://java.sun.com/xml/ns/persistence" xmlns:pkgen="http://openejb.apache.org/xml/ns/pkgen-2.1" xmlns:sec="http://geronimo.apache.org/xml/ns/security-2.0" xmlns:web="http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1">
<dep:environment>
<dep:moduleId>
<dep:groupId>dk.danicon</dep:groupId>
<dep:artifactId>ejbmodule</dep:artifactId>
<dep:version>1.0</dep:version>
<dep:type>car</dep:type>
</dep:moduleId>
</dep:environment>
</ejb:openejb-jar>
web.xml (WEB module):
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>TestWeb</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>webrealm</realm-name>
</login-config>
</web-app>
geronimo-web.xml (WEB module):
<?xml version="1.0" encoding="UTF-8"?>
<web:web-app xmlns:web="http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1" xmlns:app="http://geronimo.apache.org/xml/ns/j2ee/application-2.0" xmlns:bp="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:client="http://geronimo.apache.org/xml/ns/j2ee/application-client-2.0" xmlns:conn="http://geronimo.apache.org/xml/ns/j2ee/connector-1.2" xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.2" xmlns:ejb="http://openejb.apache.org/xml/ns/openejb-jar-2.2" xmlns:jaspi="http://geronimo.apache.org/xml/ns/geronimo-jaspi" xmlns:log="http://geronimo.apache.org/xml/ns/loginconfig-2.0" xmlns:name="http://geronimo.apache.org/xml/ns/naming-1.2" xmlns:pers="http://java.sun.com/xml/ns/persistence" xmlns:pkgen="http://openejb.apache.org/xml/ns/pkgen-2.1" xmlns:sec="http://geronimo.apache.org/xml/ns/security-2.0">
<dep:environment>
<dep:moduleId>
<dep:groupId>dk.danicon</dep:groupId>
<dep:artifactId>webmodule</dep:artifactId>
<dep:version>1.0</dep:version>
<dep:type>car</dep:type>
</dep:moduleId>
</dep:environment>
<web:context-root>/test</web:context-root>
<web:security-realm-name>webrealm</web:security-realm-name>
</web:web-app>
Sample EJB:
package dk.danicon.ejb;
import javax.annotation.security.RolesAllowed;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
#Stateless
#LocalBean
#RolesAllowed({"admin"})
public class SysTime {
public SysTime() {
}
public long getSysTime() {
return System.currentTimeMillis();
}
}
Sample servlet:
package dk.danicon.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.HttpConstraint;
import javax.servlet.annotation.ServletSecurity;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import dk.danicon.ejb.SysTime;
#WebServlet("/testsystime")
#ServletSecurity(#HttpConstraint(rolesAllowed={"admin"}))
public class TestSystime extends HttpServlet {
private static final long serialVersionUID = 1L;
#EJB
SysTime systime;
public TestSystime() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter pw = response.getWriter();
pw.println("<html><body><h3>Systime</h3>");
pw.println("<p>System time: " + systime.getSysTime() + " - " + systime.getClass().getName() + "</p>");
if(request.getUserPrincipal() != null)
pw.println("<p>Principal: " + request.getUserPrincipal().getName() + "</p>");
pw.println("</body></html>");
}
}
This appears to be an OpenEJB bug since there is no such LocalBean method interface type. That said, I am somewhat surprised that EJBMethodPermission is throwing an exception since the javadoc for that class says that implementations should be flexible enough to support unknown method interface types.