Jboss EAP 7.2 #RolesAllowed is not working inside implementation class - ejb

I have 2 modules, one describes api with just interfaces of controllers and second with implementations.
Example:
Resource interface:
#Path("/resource")
public interface Resource {
#POST
#Path("/getAll")
#Produces("application/json")
Response getAll();
Resource implementation:
#RequestScoped
#Path("/user")
public class ResourceImpl implements Resource {
#RolesAllowed({"admin"})
public Response getAll() {
When I login with user that has role "user", I'm not getting 401 or 403 error.
If I add #RolesAllowed({"admin"}) to interface, then it will work as expected. But I believe there should be other solution for it
I tried solution from this topic https://access.redhat.com/solutions/766483 but with no luck
My ejb.xml looks like so:
<ejb-jar
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"
version="3.1">
<enterprise-beans>
<message-driven>
*Queues describtion*
</message-driven>
</enterprise-beans>
<assembly-descriptor>
<method-permission>
<role-name>admin</role-name>
<method>
<ejb-name>ResourceImpl</ejb-name>
<method-name>*</method-name>
</method>
</method-permission>
</assembly-descriptor>
</ejb-jar>
I'm using Jboss EAP 7.2.9
Thanks in advance

Related

WebSocket not working on Jetty 9.4

My websocket servlet does not work on Jetty 9.4.6.v20170531 although it works perfectly with version 9.3.2.v20150730.
My code looks like this:
#SuppressWarnings("serial")
#WebServlet(name = "TcpProxy", urlPatterns = { "/sockets/tcpProxy" })
public class TcpProxySocketServlet extends WebSocketServlet {
#Override
public void configure(WebSocketServletFactory factory) {
factory.register(TcpProxySocket.class);
}
}
and
#WebSocket
public class TcpProxySocket {
/* ... */
public TcpProxySocket() {
LOGGER.info("Instantiating a TCP proxy");
}
/**
* Open a new socket
*
* #param session the session
*/
#OnWebSocketConnect
public void onConnect(Session session) throws RestException {
this.session = session;
CachedSession toriiSession = null;
...
When trying to access my socket, I get a 404 error.
On server side, the configure is never called.
I tried to force the loading of the servlet by adding it to web.xml
<servlet>
<servlet-name>TcpProxySocket</servlet-name>
<servlet-class>com.fujitsu.fse.torii.servlets.tcpProxy.TcpProxySocketServlet</servlet-class>
</servlet>
<servlet-mapping> <servlet-name>TcpProxySocket</servlet-name>
<url-pattern>/sockets/tcpProxy</url-pattern>
</servlet-mapping>
Then the servet is loaded, configure function is called.
When trying to open the socket, I don't get any error but the onConnect error is never called.
So far I have reverted to using Jetty 9.3.2, but it's not satisfying.
Any Idea ?
This was fixed by using a correct web-app markup in web.xml to use webapp version 3.1
## -1,6 +1,8 ##
<?xml version="1.0" encoding="UTF-8"?>
-<web-app version="2.5" 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_2_5.xsd">
+<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
+ version="3.1">
The other problem was that the onConnect method was never called. It disappeared when I changed the servlet mapping using a path with a trailing slash ("/sockets/scripts/" instead of "/sockets/scripts").
We could not reproduce the trailing-slash problem on a simpler example. So I'm not sure if there was an actual problem or if it was just a misinterpretation of mine.
the full story is on https://github.com/eclipse/jetty.project/issues/1800
I thank Joakim and the Jetty project for their reactivity.
I had the same issue with Java Spark web framework when they updated Jetty to 9.4.
The trailing slash issue mentioned by Michael Dussere did the trick for me, I changed the path in my client from "http://example.org/chat/" to "http://example.org//chat" (in the server it is ".../chat" as well).

Spring MVC Mixing xml and java #ContextConfiguration in integration test

I am trying to configure a Spring MVC Integration test using a combination of XML config and #Configuration annotated classes.
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#TestPropertySource({"/spring-security.properties",
"/rabbitmq-default.properties",
"/mongodb-default.properties",
"/webapp-override.properties"})
#ContextHierarchy({
#ContextConfiguration("classpath:**/security-config.xml"),
#ContextConfiguration(classes = RootConfig.class),
#ContextConfiguration(classes = SpringMvcConfig.class)
})
public class BaseConfiguredMvcIntegrationTest {
}
The java configurations are initialized correctly. The problem is although the "**/security-config.xml" file is found and parsed during initialization... all the spring security beans defined in there are never registered in the WebApplicationContext.
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1301)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1047)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
So my question is how do you utilize both XML based and annotated based configuration in a Spring MVC Integration test?
I could change the spring security config to java/annotated based one... I would rather not do this. I find using the spring security namespace more readable and concise than using the java config.
Also, note this combined XML/Java configuration works perfectly fine in a non-test environment.
Spring v4.1.6
Spring Security v4.0.1
WebApplicationContext Config:
package com.gggdw.web.config;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.DelegatingFilterProxy;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.DispatcherServlet;
#Configuration
public class GGGWebInitializer implements WebApplicationInitializer {
public static final String SERVLET_NAME = "ggg";
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(RootConfig.class);
// Manage the lifecycle of the root application context
servletContext.addListener(new ContextLoaderListener(rootContext));
// Create the dispatcher servlet's Spring application context
AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
dispatcherContext.register(SpringMvcConfig.class);
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher = servletContext.addServlet(SERVLET_NAME, new DispatcherServlet(dispatcherContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
//Spring security config
FilterRegistration.Dynamic springSecurityFilterChain = servletContext.addFilter(
"securityFilter", new DelegatingFilterProxy("springSecurityFilterChain"));
springSecurityFilterChain.addMappingForServletNames(null, false, SERVLET_NAME);
//springSecurityFilterChain.setAsyncSupported(true);
servletContext.addFilter("hiddenHttpMethodFilter", HiddenHttpMethodFilter.class);
}
}
RootConfig.class
#Configuration
#Import({WebPropertiesConfig.class, // loads all properties files on class path from resources folder
MongoConfig.class // init mongodb connection
})
#ImportResource({"classpath:**/security-config.xml"}) // spring security xml config (java config not as readable)
public class RootConfig {
}
security-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"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- <context:property-placeholder location="classpath:spring-security.properties" /> -->
<security:global-method-security pre-post-annotations="enabled" secured-annotations="enabled">
<security:expression-handler ref="expressionHandler"/>
</security:global-method-security>
<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<property name="permissionEvaluator" ref="permissionEvaluator"/>
</bean>
<bean id="permissionEvaluator"
class="com.my.local.package.security.GenericPermissionEvaluator">
</bean>
<!-- Configure Spring Security -->
<security:http auto-config="true" use-expressions="true" >
<security:form-login login-page="${spring.security.login-page}"
login-processing-url="${spring.security.login-processing-url}"
default-target-url="${spring.security.default-target-url}"
authentication-failure-url="${spring.security.authentication-failure-url}"
username-parameter="${spring.security.username-parameter}"
password-parameter="${spring.security.password-parameter}"
/>
<security:logout logout-url="${spring.security.logout-url}"
logout-success-url="${spring.security.logout-success-url}" />
<security:intercept-url pattern="/**" requires-channel="https" />
<security:intercept-url pattern="/s/**" access="isAuthenticated()" requires-channel="https" />
<security:custom-filter ref="log4JMDCFilter" after="SECURITY_CONTEXT_FILTER"/>
<security:access-denied-handler error-page="${spring.security.access-denied-handler-error-page}" />
<!-- <security:session-management invalid-session-url="${spring.security.invalid-session-url}"/>
2 types of invalid session, brand new user and a timeout of a previous logged in user
both need to be handled differently -->
</security:http>
<bean id="customUserDetailsService" class="com.my.local.package.CustomUserDetailsService" depends-on="userRepository"/>
<bean id="bCryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
<!-- log4j filter to add userName and ipAddress into logging on a per request/thread basis -->
<bean id="log4JMDCFilter" class="com.my.local.package.filter.Log4JMDCFilter"/>
<security:authentication-manager>
<security:authentication-provider user-service-ref="customUserDetailsService">
<security:password-encoder ref="bCryptPasswordEncoder"/>
</security:authentication-provider>
</security:authentication-manager>
</beans>
UPDATE: upon further consideration and based on your latest feedback, the behavior you're experiencing might be the result of a bug that was introduced in Spring Framework 4.1.4 (see SPR-13075 for details).
Try downgrading to Spring Framework 4.1.3, and let me know if you still experience the undesired behavior.
note this combined XML/Java configuration works perfectly fine in a non-test environment.
How so?
Do you literally have three (3) contexts loaded in a hierarchy in production?
I doubt that. Rather, I assume you are somehow loading a single root WebApplicationContext from "classpath:**/security-config.xml" and RootConfig.class.
Thus, the most important question is: How are you configuring the root WebApplicationContext in production?
Once you have answered that, I can tell you how to achieve the same thing in your test configuration. ;)
Regards,
Sam (author of the Spring TestContext Framework)
Pay attention to the note from PathMatchingResourcePatternResolver:
Note that "classpath*:" when combined with Ant-style patterns will only work reliably with at least one root directory before the pattern starts, unless the actual target files reside in the file system. This means that a pattern like "classpath*:*.xml" will not retrieve files from the root of jar files but rather only from the root of expanded directories. This originates from a limitation in the JDK's ClassLoader.getResources() method which only returns file system locations for a passed-in empty String (indicating potential roots to search).

Using EJBs from a different JAR

I'm developing a JAX-WS WebService in JDeveloper 11.1.1.4 that should use EJBs from a JAR previously deployed to a WebLogic server. Both the WebService project and the EJB project are my own code, but I'd like to deploy them separately. For now I'm experimenting with the setup.
In the ExampleEJB project I have a bean ExampleBean that implements a remote interface Example.
#Remote
public interface Example {
public String doRemoteStuff();
}
#Stateless(name = "Example", mappedName = "ExampleApplication-ExampleEJB-Example")
public class ExampleBean implements Example {
public String doRemoteStuff() {
return "did remote stuff";
}
}
In that project, I have two deploy descriptors (ejb-jar.xml and weblogic-ejb-jar.xml):
ejb-jar.xml
<?xml version = '1.0' encoding = 'UTF-8'?>
<ejb-jar 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_0.xsd"
version="3.0" xmlns="http://java.sun.com/xml/ns/javaee">
<enterprise-beans>
<session>
<ejb-name>Example</ejb-name>
</session>
</enterprise-beans>
</ejb-jar>
weblogic-ejb-jar.xml
<?xml version = '1.0' encoding = 'UTF-8'?>
<weblogic-ejb-jar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.bea.com/ns/weblogic/weblogic-ejb-jar http://www.bea.com/ns/weblogic/weblogic-ejb-jar/1.0/weblogic-ejb-jar.xsd"
xmlns="http://www.bea.com/ns/weblogic/weblogic-ejb-jar">
<weblogic-enterprise-bean>
<ejb-name>Example</ejb-name>
<stateless-session-descriptor/>
</weblogic-enterprise-bean>
</weblogic-ejb-jar>
Additionaly, I've created an EJB JAR deployment profile named example-ejb.jar and managed to deploy it to the server.
In the ExampleWS project I have an ExampleWebService:
#WebService(serviceName = "ExampleWebService")
public class ExampleWebService {
#EJB
Example example;
public String doStuff() {
return example.doRemoteStuff();
}
}
I added the ExampleEJB project dependency to this project (so it would compile). The only XML I have in this project is the web.xml used to describe the servlet. Also, I have the WebServices WAR file created automatically by jDeveloper when creating a WebService. Lastly, I created an EAR deployment profile named example-ws that only includes the WebServices WAR file in it's application assembly.
What do I need to do for this to work? Also, what would the procedure be if the ExampleEJB project was referenced from another project (say, AdditionalExampleEJB) that has additional beans that use ExampleBean? How would I reference the ExampleBean from there?
Thank you VERY MUCH for any help you can give me!
EDIT:
I've managed to reference the EJB from the WebService!
In the ExampleEJB project I modified the weblogic-ejb-jar.xml and now it looks like this:
weblogic-ejb-jar.xml
<?xml version = '1.0' encoding = 'UTF-8'?>
<weblogic-ejb-jar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.bea.com/ns/weblogic/weblogic-ejb-jar http://www.bea.com/ns/weblogic/weblogic-ejb-jar/1.0/weblogic-ejb-jar.xsd"
xmlns="http://www.bea.com/ns/weblogic/weblogic-ejb-jar">
<weblogic-enterprise-bean>
<ejb-name>Example</ejb-name>
<stateless-session-descriptor>
<pool>
<max-beans-in-free-pool>10</max-beans-in-free-pool>
<initial-beans-in-free-pool>3</initial-beans-in-free-pool>
</pool>
<business-interface-jndi-name-map>
<business-remote>hr.example.Example</business-remote>
<jndi-name>ejb/example-ejb/Example</jndi-name>
</business-interface-jndi-name-map>
</stateless-session-descriptor>
</weblogic-enterprise-bean>
</weblogic-ejb-jar>
In the ExampleWS project I added a deployment descriptor weblogic.xml that looks like this:
weblogic.xml
<?xml version = '1.0' encoding = 'UTF-8'?>
<weblogic-web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.bea.com/ns/weblogic/weblogic-web-app http://www.bea.com/ns/weblogic/weblogic-web-app/1.0/weblogic-web-app.xsd"
xmlns="http://www.bea.com/ns/weblogic/weblogic-web-app">
<ejb-reference-description>
<ejb-ref-name>ExampleReference</ejb-ref-name>
<jndi-name>ejb/example-ejb/Example</jndi-name>
</ejb-reference-description>
</weblogic-web-app>
Note that the ExampleReference value and ejb/example-ejb/Example value are something I decided to enter - I think they is more or less a developer's choice.
Also, I referenced the EJB in my WebService using the ExampleReference value, so my ExampleWebService looks like this:
ExampleWebService
#WebService(serviceName = "ExampleWebService")
public class ExampleWebService {
#EJB(
name="ExampleReference"
)
Example example;
public String doStuff() {
return example.doRemoteStuff();
}
}
Lastly, in the deployment profile of ExampleWS (the WebServices.war) I added the dependency contributor and checked the interface Example.class element (NOT the ExampleBean.java that has the implementation).
Now, how would this work if the Example bean was referenced from another EJB project (not a WebService)?
So, for all those that encounter the same problem, I have solved it. There is no way to look up a remote EJB in EJB 3.0 other than using InitialContext.lookup("jndi/name"). Also, narrowing the object seems to help in some ClassCastException situations, so I tend to do it as a precaution. This is how I look up my EJBs:
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;
public Object lookup (String jndiName, Class type) throws NamingException {
return PortableRemoteObject.narrow(InitialContext.doLookup(jndiName), type);
}
If using EJB 3.1, there is a way using #EJB(lookup = "jndi/name"), but since I'm not using this version, I cannot guarantee that this works.

Spring MVC or Wicket?

I have a long (and happy so far) experience with Spring MVC, but lately I'm getting interested in Wicket.
My question is also on how to handle (with Wicket) DI, Transaction Mgmt, JDBC connections and all that stuff? Is it okay to mix certain parts of the Springsource suite with Wicket? Wicket & Weld? Wicket & Guice?
Wicket is a presentation-layer framework. It will not handle DI, transactions or connections.
But it can be easily integrated with a number of frameworks, including Spring, Guice (official Wicket modules, wicket-spring and wicket-guice) and CDI/Weld (wicket-cdi, a side project from Igor Vaynberg, one of the Wicket committers).
Wicket Wiki: Integration guides
Below, a simple Wicket application with Spring. The transaction bits are plain old Spring configuration, so I didn't bother including them.
HelloWorldService.java
public class HelloWorldService {
private String message;
public void setMessage(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
applicationContext.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.1.xsd">
<bean id="helloWorldService" class="minimal.wicketspring.HelloWorldService">
<property name="message" value="Hello, World!" />
</bean>
</beans>
WicketApplication.java
public class WicketApplication extends WebApplication {
#Override
public void init() {
super.init();
getComponentInstantiationListeners().add(new SpringComponentInjector(this));
}
#Override
public Class<HomePage> getHomePage() {
return HomePage.class;
}
}
HomePage.java
public class HomePage extends WebPage {
#SpringBean
private HelloWorldService helloWorldService;
public HomePage() {
add(new FeedbackPanel("feedback"));
add(new Link<Void>("link") {
#Override
public void onClick() {
info(helloWorldService.getMessage());
}
});
}
}
HomePage.html
<!DOCTYPE html>
<html xmlns:wicket="http://wicket.apache.org">
<body>
<div wicket:id="feedback"></div>
<a wicket:id="link">Show Message</a>
</body>
</html>
web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app 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_2_5.xsd" version="2.5">
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>wicket.wicket-spring</filter-name>
<filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
<init-param>
<param-name>applicationClassName</param-name>
<param-value>minimal.wicketspring.WicketApplication</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>wicket.wicket-spring</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
Wicket effectively replaces Spring MVC, but not the Spring container itself. Wicket integrates easily with Spring via #SpringBean annotation which allows you to inject Spring beans (services, DAOs, etc.) directly to pages. You cannot perform DI the other way around - for a good reason.
It is a smart choice to use Spring and Wicket together. However as far as I remember Wicket pages and components aren't managed by Spring container so you cannot use #Transactional annotation on them (which is a bad idea anyway - transactions belong to deeper levels).
Everything else works exactly the same - AOP, JDBC, etc.
I would recommend to leave Spring entirely and try the Java EE 6 + Wicket 6.x. I was using Spring MVC, then Spring + Wicket in the days of Java EE 5 but Java EE 6 as the middleware layer simply beats Spring solutions.
Update 2017:
With the new goodies in Java 7 and 8 (lambdas, method refereces, default interface method implementations, ...), the Java EE 7 + Wicket 8 combo is even more appealing. Although Spring MVC is quite popular and might have better learning curve, once you try Wicket you'll miss it when you get to the "next cool thing" (Angular2 in my case).
Note: I am paid by Red Hat, but the above is my honest opinion. In 2011, I'd tell you to go with Spring.
Just forget on wickets. Simple spring MVC, Twitter bootstrap layout and whole spring portfolio let you create scalable and top high performance applications, with top security. Wickets is pain as soon as you go behind your first impress and start real development.
http://www.slideshare.net/mraible/comparing-jvm-web-frameworks-february-2014 hope thi help make decision for me this presentation was realy helpfull.

Jython and implementing HttpServlet.contextInitialized

I'd like my Jython servlet to implement the HttpServlet.contextInitialized method but I'm not sure how to express this in the web.xml. What I currently have is:
from javax.servlet import ServletContextListener;
from javax.servlet.http import HttpServlet
class JythonServlet1 ( HttpServlet, ServletContextListener ):
def contextInitialized( self, event ):
print "contextInitialized"
context = event.getServletContext()
def contextDestroyed( self, event ):
print "contextDestroyed"
context = event.getServletContext()
def doGet( self, request, response ):
print "doGet"
def doPost( self, request, response ):
print "doPost"
And my web.xml looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>JythonTest</display-name>
<servlet>
<servlet-name>PyServlet</servlet-name>
<servlet-class>org.python.util.PyServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>PyServlet</servlet-name>
<url-pattern>*.py</url-pattern>
</servlet-mapping>
<servlet>
<description></description>
<display-name>JythonServlet1</display-name>
<servlet-name>JythonServlet1</servlet-name>
<servlet-class>JythonServlet1</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
</web-app>
As you can see, in the last <servlet> entry I'd like to initialize the servlet with the context (where I can start a scheduler) but it doesn't seem to work the same as with a Java servlet.
I don't do Jython, but there's no means of contextInitialized or contextDestroyed methods in the HttpServlet API. You're probably looking for ServletContextListener interface which is normally to be implemented as the following Java-based example:
package com.example;
import javax.servlet.ServletContextListener;
public class MyServletContextListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
// ...
}
public void contextDestroyed(ServletContextEvent event) {
// ...
}
}
...which is to be definied as <listener> in web.xml as follows:
<listener>
<listener-class>com.example.MyServletContextListener</listener-class>
</listener>
This must give you an idea how to pickup it using Jython.
You can optionally also let your servlet both extend HttpServlet and implement ServletContextListener like follows:
public class MyServlet extends HttpServlet implements ServletContextListener {
// ...
}
so that you can end up with the code you've posted (don't forget to import the particular interface and define your class as both servlet and listener in web.xml). But this is not always considered a good practice.
That said, you should be placing classes in a package to avoid portability problems. It may work in some environments, but not in other. Sun also discourages using packageless classes in non-prototyping environments. They can normally namely not be imported by other classes which are itself in a package.
You really need to write some java bootstrapper like PyServlet that dispatches init() to a pre-defined python script.
Or.. if you want to use the ServletContextListener interface then something like Pyservlet that also implements ServletContextListner and again, dispatches to some python script.
I'm looking for a similar solution and was very disappointed to see that PyServlet doesn't offer anything like this itself.

Resources