I am trying to do something at startup using a startup ejb. But my bean is never called.
This is my bean:
import javax.annotation.PostConstruct;
import javax.ejb.Startup;
import javax.inject.Singleton;
#Singleton
#Startup
public class StartupBean {
#PostConstruct
public void doSomething(){
System.out.println("why??");
}
}
I am using jboss 7.1.1.
What am i doing wrong? You can find my source code at bitbucket: https://bitbucket.org/cremersstijn/jee/src/9e22ed2b798a/simple-startup-bean
You're importing the wrong Singleton. If you want to create a singleton session bean, use javax.ejb.Singleton.
http://docs.oracle.com/javaee/6/api/javax/ejb/Singleton.html
vs.
http://docs.oracle.com/javaee/6/api/javax/inject/Singleton.html
Related
Hi everyone I have the following code trying to use CDI's #produces
import java.sql.Connection;
import javax.enterprise.inject.Produces;
public class ConnectionSupplier
{
#Produces
//#RequestScoped
#Connect
public Connection getConnection()
{
//get connection from datasource
}
}
And this is #connect Qualifier
//remove imports
#Qualifier
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD, ElementType.FIELD})
public #interface Connect{}
and here we make injection
import com.seta.history.db.entities.Day;
import java.sql.Connection;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
#RequestScoped
#Named("day")
public class DayController
{
#Inject
#Connect
private Connection connection;
public void save(Day day)
{
//do-save
}
}
but it gives the following exception
Severe: Exception during lifecycle processing
org.glassfish.deployment.common.DeploymentException: CDI deployment
failure:WELD-001408: Unsatisfied dependencies for type Connection with
qualifiers #Connect
at injection point [BackedAnnotatedField] #Inject #Connect private
com.seta.history.db.controllers.DayController.connection
at
com.seta.history.db.controllers.
DayController.connection(DayController.java:0)
I am using Java EE 7 + GlassFish 4.1.2
NOTE we usually used Glassfish and CDI and it works fine
so can anyone help And thanks in advance
In CDI > 1.0, if you do not have any beans.xml, CDI only scans annotated classes. So CDI does not take into account your ConnectionSupplier class and the producer.
You have two ways to correct this :
Annotate your ConnectionSupplier class (for example with #ApplicationScoped)
Add a beans.xml with bean-discovery-mode="all" to tell CDI to scan all classes.
im little confused. What is the exact difference between javax.inject.Singleton and javax.ejb.Singleton?
I found a plausible explanation here:
By default, javax.ejb.Singleton session beans are transactional (section 13.3.7 of the EJB 3.1 specification) and require acquisition of an exclusive lock for every business method invocation (sections 4.8.5.4 and 4.8.5.5).
In contrast, a javax.inject.Singleton is not transactional and does not support container-managed concurrency (the major consequence being that no locking scheme is implemented by the container). [...]
If you don't need EJB features, stick with #ApplicationScoped (javax.inject.Singleton is not defined by CDI, and its semantics are therefore not governed by that specification).
To reduce future confusion, I use this small unit test (first level package name needs to be replaced):
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import org.junit.Test;
public class SingletonTest {
/** requires com.tngtech.archunit:archunit-junit:0.4.0 */
#Test
public void detectWrongSingletonAnnotation() {
final ClassFileImporter importer = new ClassFileImporter();
final JavaClasses classes = importer.importPackages("first_level_package");
noClasses().should().beAnnotatedWith("javax.inject.Singleton")
.as("Please use javax.ejb.Singleton instead of javax.inject.Singleton.")
.check(classes);
}
}
Since accepted answer didn't solve my problem I post my own answer. It won't be as good as article by Adam Bien but definitely will be more practical:
Consider following code:
import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
#Singleton
public class DatabaseConnection {
#PostConstruct
public void init() {
System.out.println("init");
}
public ChampionComp getFirstRecord() {
return new ChampionComp("Ashe", "Teemo", "Warwick",
"Blitzcrank", "Syndra", "Anivia", "Brand", "Rammus", "Xin Zhao", "Irelia");
}
}
And this REST service:
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.Path;
#Path("/champions")
public class ChampionsAPI {
#Inject
private DatabaseConnection db;
#GET
#Produces("text/plain")
public String getClichedMessage() {
ChampionComp comp = db.getFirstRecord();
return comp.toString();
}
}
Using javax.ejb.Singleton this code works just fine. The DatabaseConnection instance is created once and injected to REST service.
However when replacing ejb in import with inject you would receive NPE in ChampionsAPI class while accessing db field - that's because your Singleton was not created (for some reason, maybe because one need to make use of interfaces while using javax.inject.Singleton ? ).
In simple clarity:
javax.ejb.Singleton is an annotation used to create an #Singleton EJB (as opposed to #Sateless EJB or #Stateful EJB)
On the other hand, javax.inject.Singleton is an annotation used to create a CDI with singleton scope
So basically, one creates a singleton EJB while the other creates a CDI with singleton scope
I have created a simple EJB 3.0 application, deployed in JBOSS 7.1.1 final.
Here is the code:
EJB 1:
Interface
package com.example.server.local.bean;
import javax.ejb.Local;
#Local
public interface UtilLocalBeanLocal {
public String addString();
}
Class implementing this interface:
package com.example.server.local.bean;
import javax.ejb.Local;
import javax.ejb.Stateless;
#Stateless
#Local(value=UtilLocalBeanLocal.class)
public class UtilLocalBean implements UtilLocalBeanLocal {
public UtilLocalBean() {
}
#Override
public String addString() {
return "Added from Local bean";
}
}
So, this EJB i am creating to be "locally" used by another EJB.
EJB 2:
Interface
package com.example.bean.session;
import javax.ejb.Remote;
#Remote
public interface FirstBeanRemote {
public String callMe();
}
Class implementing this interface.
package com.example.bean.session;
import javax.ejb.EJB;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import com.example.server.local.bean.UtilLocalBeanLocal;
#Stateless
#Remote(value=FirstBeanRemote.class)
public class FirstBean implements FirstBeanRemote {
#EJB
private UtilLocalBeanLocal utilLocalBeanLocal;
public FirstBean() {
}
#Override
public String callMe() {
return "Hi there!" + utilLocalBeanLocal.addString();
}
}
When i start the JBOSS, the JNDI bindings i get are like this:
00:34:15,928 INFO [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-5) JNDI bindings for session bean named FirstBean in deployment unit subdeployment "EJB30TestProj.jar" of deployment "EJB30TestProjEAR.ear" are as follows:
java:global/EJB30TestProjEAR/EJB30TestProj/FirstBean!com.example.bean.session.FirstBeanRemote
java:app/EJB30TestProj/FirstBean!com.example.bean.session.FirstBeanRemote
java:module/FirstBean!com.example.bean.session.FirstBeanRemote
java:jboss/exported/EJB30TestProjEAR/EJB30TestProj/FirstBean!com.example.bean.session.FirstBeanRemote
java:global/EJB30TestProjEAR/EJB30TestProj/FirstBean
java:app/EJB30TestProj/FirstBean
java:module/FirstBean
However in the remote client when I try to use any of these above JNDI binding values, it is not working, and what actually works (after lot of google) is:
ejb:EJB30TestProjEAR/EJB30TestProj//FirstBean!com.example.bean.session.FirstBeanRemote
It is difficult to understand how this JNDI bindings work. JBOSS outputs a different JNDI and in reality what works is different one.
Can anyone please demystify this? (how to decide which JNDI bindings will work in different scenarios and any further pointers)
The binding values that you mention are prepared for lookup locally, let say into the server that you publish the ejb. global, module, app are the scopes limit and in which you can use each one. For example, you could lookup a ejb from other ejb of the same ejb-module using module scope but you couldn't lookup it from another ejb-module even being modules of the same app (ear or war), you must use at least app scope for that, and you can use app or global in both scenarios.
I strongly suggest you to take the time to read Jboss AS7 JNDI Referencia but to know about remote lookup go to Remote JNDI section
We are using Spring Framework (XML Version) 4.0.5.RELAESE in our Java project.
In our application the context.xml is instantiated at the begin of the application start, and provides every properties via dependecy injection.
Now I am wondering what is the best (and commonly used) strategy on where to instantiate it in the test environment. (We have some Unit, Integration and System tests who at least need the databaseBaseConnector bean provided in the context.xml,)
I thought about making an abstract class which every test extends from, but in this case it would be newly instantiated before every test. I would like to a have a solution similiar to the main application, where the context is only instantiated one time, and everything else needed is set via dependency injection.
Researching this topic didn`t help much yet, so I decided to ask the question.
Spring comes with an SpringJUnit4ClassRunner and a #ContextConfiguration -annotation. If you use them, then spring will reuse the same Spring Context in different tests.
So a Spring test class can look like this:
package com.queomedia;
import javax.annotation.Resource;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
#RunWith(SpringJUnit4ClassRunner.class)
//#Transactional
#ContextConfiguration(SpringTestContext.APPLICATION)
public class SpringContextTest {
#Autowire
private ApplicationContext applicationContext;
//Test that the spring context can been loaded
#Test
public void testSpringContextLoad() {
Assert.assertNotNull("application context expected", this.applicationContext);
}
}
I have a spring bean that I have configured in applicationContext like below:
<bean id="beanIRPlus" class="org.jadefalcon.demo.server.Spring.beans.BeanIRPlus" />
Then I have a Hibernate Service like below that I am trying to inject into the Spring bean. Normally, for example, if I use a prototype bean thats injected into my controller and that has an injected Hibernate service it works fine, however for this particular bean it is a singleton so its created when the application starts up. I made sure to even put the bean declaration at the very end of the applicationContext.xml file figuring maybe it has to be put after anything Hibernate related but the issue is still persisting. Its giving a null pointer exception, that the CasesService object doesn't exist. Any advice on what I'm doing wrong is greatly appreciated:
import javax.annotation.Resource;
import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.jadefalcon.demo.domain.Cases;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
#Service("casesservice")
#Transactional
public class CasesService {
protected static Logger logger = Logger.getLogger("service");
#Resource(name = "sessionFactory")
private SessionFactory sessionFactory;
public void add(Cases cases) {
logger.debug("Saving new search");
// Retrieve session from Hibernate
Session session = sessionFactory.getCurrentSession();
// Save
session.save(cases);
}
}
I didn't see how you are trying to inject it. You have at least two options:
xml. Define a <property name=".." ref="casesservice"> in your controller bean definition
annotations. Use #Autowired private CaseService service (or #Inject)