I'm trying to init CDI-SE context inside my Quartz Application, so i have the following dependency (maven):
<dependency>
<groupId>org.jboss.weld.se</groupId>
<artifactId>weld-se-core</artifactId>
<version>2.3.4.Final</version>
</dependency>
Inside my JobQuartz i have the method execute() with the following:
public void execute(JobExecutionContext context) throws JobExecutionException {
Weld weld = new Weld();
WeldContainer container = weld.initialize();
service = container.instance().select(MyService.class).get();
service.go();
weld.shutdown();
}
But i got the following error:
Caused by: java.lang.IllegalStateException: WELD-ENV-002009: Weld SE container cannot be initialized - no bean archives found
My project is a WAR, so i putted beans.xml file inside /src/main/webapp/META-INF/, see the content:
<?xml version="1.0"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
version="1.2" bean-discovery-mode="all">
</beans>
I copied the file to /src/main/resource/META-INF, but i got the same error.
After some conversation in comments section I think I understand enough to answer you.
First of all, you should not start Weld SE container on your own as you then have two containers running side by side (which isn't intended/supported) - one SE and one "classic", handled by the container. Stick with the container-handled one, which is booted for you effortlessly.
Now, I see you are missing some scope activation means. If you are using some newer version of Weld, you can make use of an interceptor, which will activate RequestContext (I suppose that's the one you are after) before a method and tear it down afterwards. All you need for that is a dependency on Weld API (which is included in WFLY anyway) and then you simply annotate your method or class with that.
For the above you need Weld 2.4.x. Note that you can quite simply patch your WildFly. The patches are at the bottom of the Weld website and the how-to can be found here.
If you were to use Weld 3/CDI 2.0 then there is even a built-in bean (RequestContextController) which allows you to control this lifecycle.
Other option is then Deltaspike, as Johm Ament pointed out, but that requires you to bring in another dependency.
If what you're trying to do is start a request context, you have a couple of solutions.
Use DeltaSpike's Quartz Integration for CDI - http://deltaspike.apache.org/documentation/scheduler.html
Programmatically start and stop a context using BoundRequestContext (it's a CDI bean you can inject).
I would strongly recommend the DeltaSpike approach, since it takes care of all of the setup you would need for the job to automatically start the context.
Related
My technical stack includes
Tomcat 8.5.47 (plain, not EE)
Weld 2.4.8.Final (as a reference implementation of CDI 1.2)
To be able to use ManagedExecutorService and manage threads more wisely and in a safer manner, I would like to include this dependency
org.glassfis:javax.enterprise.concurrent (as a reference implementation of JSR 236 [Concurrency Utilities])
I tried to inject the bean in different ways and into differently-scoped beans (view-, session-, application-based).
#Inject
private javax.enterprise.concurrent.ManagedExecutorService service;
#Resource
private javax.enterprise.concurrent.ManagedExecutorService service;
#Resource(lookup="java:comp/DefaultManagedExecutorService")
private javax.enterprise.concurrent.ManagedExecutorService service;
Nothing seems to work and the exception goes
java.lang.RuntimeException:
Error looking up java:comp/env/.../ManagedExecutorService in JNDI
javax.naming.NameNotFoundException:
Name [.../ManagedExecutorService] is not bound in this Context.
It might be due to improper bean registration. Because I found none. I scanned the whole classpath and couldn't find anything that defines ManagedExecutorService or any of its implementations somewhere.
I tried to register it by myself in the context.xml to no avail. I used this TomEE tutorial (naively) assuming that configuration for my non-EE Tomcat would be the same.
<Resource name="ManagedExecutorService"
type="javax.enterprise.concurrent.ManagedExecutorService" />
<Resource id="ManagedExecutorService"
type="javax.enterprise.concurrent.ManagedExecutorService" />
Apparently, it's not.
My questions are
Is it possible to set up Concurrency Utilities on a non-EE server, Tomcat 8.5 in particular?
If so, what am I missing here?
I can't switch to any JavaEE application server.
I can't upgrade the listed dependencies.
Related:
Java EE specification and multi threading
Is it safe to manually start a new thread in Java EE?
Why am I getting a WELD-001303: No active contexts for scope type javax.enterprise.context.RequestScoped exception?
The background & requirements are:
there are a lot of old projects which have an applicationContext.xml and one or more dispatcher[-XXX]-servlet.xml. We hope those projects can still works while using spring boot(we developed a deployment tools to deploy spring boot applications, but the old projects are still deployed manually). But, #SpringBootApplication can't build the contexts as they were. And rewriting them into codes one by one costs too much, I think.
In those project, we use an extended RequestMappingHandlerMapping, so we can't use the native MVC.
the context.xml of tomcat, which contains jndi definitions, is maintained by OPs. We have to load it just like tomcat does.
i can't find where to set welcome file, which were set in web.xml
I currently using:
#Configuration
#ImportResource({"classpath:/applicationContext.xml", "classpath:/dispatcher-servlet.xml"})
Those simple projects without using jndi can startup.
But as my understanding, in this case, the applicationContext and dispatcher-servlet are in the same level(dispatcher-servlet should the child of applicationContext, isn't it?). So, i can't even ensure this one works properly.
We did a similar thing about a year ago and your setup was more or less the same as ours and importing those XML files did the trick; the only thing we had to do was to ensure our application class was in a different package hierarchy in order to avoid conflicting/duplicate bean definitions due to its inherent #ComponentScan.
And having dispatcher servlet and application context in the same context won't cause any issues - yes, dispatcher servlet's context is usually defined as a separate context and is a child of the more broad applicationContext but what most people fail to grasp is that that separation only matters if your application wants to have more than one dispatcher servlet, which is rarely the case any more, if it ever was.
In case of multiple dispatcher servlets it was a must to enable them to have different WebMVC configurations, and applicationContext was there to allow you to share common beans and configuration between your servlet contexts so that you don't have to do the same work twice.
I'm puzzled by this section of spring documentation.
For example, to create an application context and use dependency injection to configure an application, your Maven dependencies will look like this:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.5.RELEASE</version>
<scope>runtime</scope>
</dependency>
</dependencies>
Note the scope can be declared as runtime if you don’t need to compile against Spring APIs, which is typically the case for basic dependency injection use cases.
I know about JSR 330 (DI annotations). But how do you decouple from ApplicationContext class? And if you do decouple from it why then still depend on spring?
How, for example, can quick start be rewritten having spring-context as a runtime dependency? Or what would be the "basic dependency injection use case"?
I think the "basic use case" is referring to XML-based application contexts. That documentation is saying if you aren't directly using Spring libraries in your code, then you won't have to include those libraries in your compilation classpath. This is the case with XML configurations, as everything is Spring related is configured in XML, and therefore is not compiled.
In the quick start you've linked, the author is using annotation-based application context configuration, which would require the Spring libraries to be included both at compile- and runtime.
Sample XML configuration:
http://www.springbyexample.org/examples/intro-to-ioc-creating-a-spring-application.html
there should only be a few key points where the application code needs to directly access the IoC container [...]. If you're developing a web application, you may not need to directly access the IoC container at all since it will automatically handle instantiation of your controller and any beans it requires.
I'm not completely familiar with it, but it also looks like you can use JSR330 as you suggested with an XML configuration to autowire beans using annotations.
See here. This would allow using annotations, but without the need to include Spring in compile-time configurations.
1
First of all, let's talk about DI.
Note from Spring Doc,
Dependency management and dependency injection are different things.
Dependency management is "assemble all the libraries needed (jar files) and get them onto your classpath at runtime, and possibly at compile time".
Dependency injection is, suppose you want a Service object in your class, instead of create it using service = new Service();, you let the spring framework handle the life cycle of that bean.
Example of Dependency management:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
</dependencies>
So that you have all these jar files in your project.
spring-context-4.2.5.RELEASE.jar
spring-aop-4.2.5.RELEASE.jar
spring-beans-4.2.5.RELEASE.jar
spring-core-4.2.5.RELEASE.jar
Example of Dependency Injection:
In your quick-start example, you inject MessageService into MessagePrinter by using constructor injection. You didn't create a MessageService anywhere. Spring container creates it for you.
#Component
public class MessagePrinter {
final private MessageService service;
#Autowired
public MessagePrinter(MessageService service) {
this.service = service;
}
public void printMessage() {
System.out.println(this.service.getMessage());
}
}
#Configuration
#ComponentScan
public class Application {
#Bean
MessageService mockMessageService() {
return new MessageService() {
public String getMessage() {
return "Hello World!";
}
};
}
...
}
2
Now let's talk about transitive dependency and run-time dependency.
Transitive dependency
It means to discover the libraries that your own dependencies require and including them automatically.
For example, if you specified dependencies A and B in pom.xml. And A depends on C, D. B depends on E. You don't need to include C, D, E in your configuration.
Because of transitive dependency, C, D, E will be included automatically.
Runtime dependency
It is one type of dependency scopes to limit the transitive dependency.
"This scope indicates that the dependency is not required for
compilation, but is for execution. It is in the runtime and test
classpaths, but not the compile classpath."
3
Now the question is: is there any case that for DI "you don’t need to compile against Spring APIs", instead you can set the scope as runtime? Similar question here.
Yes, one example I can think of is web application. Suppose I'm using Strtuts with Spring plugin. (below example comes from "Struts 2 in Action" from Manning)
I want to tell Spring to create an instance of the Login class to use as its action object for the request.
add a spring web context listener to web.xml
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
define a bean Login named as springManagedLoginAction in
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-2.0.xsd">
<bean id="portfolioService" class="manning.chapterNine.utils.PortfolioServiceJPAImpl"/>
<bean id="springManagedLoginAction" class="manning.chapterNine.Login" scope="prototype">
<property name="portfolioService" ref="portfolioService"/>
</bean>
</beans>
use this bean in the action class in struts-config-login.xml
<action name="Login" class="springManagedLoginAction">
<result type="redirectAction">
<param name="actionName">AdminPortfolio</param>
<param name="namespace">/chapterEight/secure</param>
</result>
<result name="input">/chapterEight/Login.jsp</result>
</action>
I am not sure I understood your question correctly, but it seems to me that why you are asking why do you need to have spring-context dependency if you are using JSR-330 annotations.
Well, the answer from my point of view is you don't actually need the dependency on Spring if you are using only JSR-330 annotations but in order for them to work, you need some library which understands them and correctly builds the dependency graph for you and spring-context is one of such library.
The reason why it is a runtime dependency is because you can switch this provider at runtime, at least in theory.
You can implement your beans with a dependency on javax.inject (#Named, #Inject) in separate bundle. They will be usable from spring based project or any other container which has their own DI implementation.
Here is sample of reworking spring based components to javax.inject (without splitting project to different bundles)
http://www.mkyong.com/spring3/spring-3-and-jsr-330-inject-and-named-example/
If I understand correctly you are basically asking how the dependency injector is initialized and how you can inject the dependencies in your classes. In the quick start example you provided the application context is created manually in the main class.
ApplicationContext context =
new AnnotationConfigApplicationContext(Application.class);
According to the documentation
Standalone application context, accepting annotated classes as input -
in particular #Configuration-annotated classes, but also plain
#Component types and JSR-330 compliant classes using javax.inject
annotations. Allows for registering classes one by one using
register(Class...) as well as for classpath scanning using
scan(String...)
An alternative way to initialize spring is within your web.xml, where you use the ContextLoaderListner which will bootstrap the spring application context for you when the programs starts.
The question about how to start spring in web.xml has already been answered here.
I'v mostly used XML based configuration for applicationContexts. I have a requirement where I need to use #configuration to create my beans using #Bean now.
Brief description of why ?
weblogic deploys a spring web-app "A". A makes calls to B(not spring,not web app-no WEB_INF). B just contains common service calls to external servers. Hence B.jar is bundled into A and A is then deployed on web-logic.
Now i need to use spring beans in B.)
So the options available at this point:
Bundle applicationContext.xml and all the property files into B.jar. (keep in mind it is a very complex build process with 20 property files and 100s of beans. So I also need to register propertymanager bean etc..). Then initialize appcontext in a static initializer block and look for appcontext within B.jar.
Use #configuration to register an Appconfig.class instead of an XML. (no changes to build process here).
With this option i need to use a clientInterceptor. Could you provide me with the #Bean definition of this.
How do I configure clientInterceptor in #appconfig.class.
*please let me know if there any other options.
Spring-ws-core - 2.1.4.release
spring-core-3.2.4
expression,context,beans - 3.0.5
spring-oxm-1.0.3
weblogic - 12c
jdk - 1.7
This is my first post here. Any suggestions would be welcome and appreciated. Apologize for any forum faux paus.
I'm writing my first Java EE (EJB + Servlets etc.) application (please note: I'm using Eclipse).
I'm stuck with a problem with EntityManager injection not working, and having some difficulties finding why due to my Java EE (and Java in general) noobness.
Here is my persistence.xml file - I think this is mostly correct, since I can launch the HSQL database manager from the JMX console and my PUBLIC.USER table shows up correctly.
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="MyPu">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/DefaultDS</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
</properties>
</persistence-unit>
</persistence>
Here's my servlet code:
[...]
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws
String id = request.getParameter("username");
String password = request.getParameter("password");
UserManagerBean um = new UserManagerBean();
um.register(username, password);
RequestDispatcher dispatcher=getServletContext().getRequestDispatcher("/index.jsp");
dispatcher.forward(request, response);
}
And here's my UserManagerBean Class:
//bunch of imports
import myPackage.UserManager;
public #Stateful class UserManagerBean implements UserManager {
#PersistenceContext(unitName="MyPu")
private EntityManager persistManager;
public void register(String username, String password) {
User user = new User(userame, password);
persistManager.persist(user);
persistManager.flush();
}
}
The persistManager.persist(user) line throws a NullPointerException.
From my own searching I understood that this is happening because, since I'm calling new() on UserManagerBean the injection from the #PersistenceContext annotation never takes place and persistManager never gets bound.
If so, it is evident that I'm missing something about the proper usage of EJBs.
What is the right way to instantiate my bean? What's with the interfaces? I'm not entirely sure if my bean should be stateful or stateless :\
Additional info:
I changed code in my servlet, from
UserManagerBean um = new UserManagerBean();
to
#EJB
private UserManagerBean um;
in the appropriate place. Now um is the NullPointer.
Quoting Referencing EJB3 Session Beans from non-EJB3 Beans from the JBoss documentation:
JBoss Application Server 4.2.2 implemented EJB3 functionality by way of an EJB MBean container running as a plugin in the JBoss Application Server. This had certain implications for application development.
The EJB3 plugin injects references to an EntityManager and #EJB references from one EJB object to another. However this support is limited to the EJB3 MBean and the JAR files it manages. Any JAR files which are loaded from a WAR (such as Servlets, JSF backing beans, and so forth) do not undergo this processing. The Java 5 Enterprise Edition standard specifies that a Servlet can reference a Session Bean through an #EJB annotated reference, this was not implemented in JBoss Application Server 4.2.2.
So even though the Java EE 5 specification stipulates a wider scope of the #EJB annotation, JBoss 4.2.2 doesn't support it. In fact JBoss 4.2.2 is a transitional version that doesn't claim full Java EE 5 compliance.
Consequently, either:
Stick with you actual version of JBoss but use a JDNI lookup to get your bean - or -
Swith to JBoss 5 AS that fully supports the entire Java 5 Enterprise Edition specification (but has horrible startup performances) - or -
Swith to another Java EE 5 application server like GlassFish v2 (or even v3) or WebLogic 10. I'd go with GFv3.
As Petar Minchev said in the comments above #EJB doesn't work in servlets with JBoss 4.2.
In your WAR (in the WEB-INF directory) you'll need to modify two files:
web.xml:
<ejb-local-ref>
<ejb-ref-name>ejb/UserManager</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local-home/>
<local>myPackage.UserManager</local>
</ejb-local-ref>
jboss-web.xml:
<?xml version='1.0' encoding='ISO-8859-1'?>
<!DOCTYPE jboss-web PUBLIC "-//JBoss//DTD Web Application 2.3//EN" "http://www.jboss.org/j2ee/dtd/jboss-web_3_2.dtd">
<jboss-web>
<ejb-local-ref>
<ejb-ref-name>ejb/UserManager</ejb-ref-name>
<local-jndi-name>[earname]/UserManagerBean/local</local-jndi-name>
</ejb-local-ref>
</jboss-web>
You can then get an instance of your EJB by doing:
UserManagerBean um = (UserManager)new InitialContext().lookup( "java:comp/env/ejb/UserManager" );
As per the comments, it turns out that you indeed are using an appserver which doesn't support it at all -as I expected. To resolve this, you have 3 options:
Use "good old" XML config files.
Upgrade the server (there's already a stable 5.1.0).
Replace the server (I can recommend Glassfish v3 to be the most up-to-date).
To enable dependency injection on your project make sure that you have the file "beans.xml" and it is properly located.
For WAR packaging the location is src/main/webapp/WEB-INF/
For JAR and EAR packaging the location is src/main/resources/META-INF/
If you have several maven modules you must have it on each module.
More information about beans.xml