I'm using a stateless EJB via the #EJB annotation... most of the time everything works as it should but it seems that from time to time what is supposed to be injected resolves to a NULL causing a null pointer exception.
What could cause this intermittent problem?
JBoss 4.x won't automatically inject EJB's into Servlets/JSPs/POJOs. But it won't complain about the annotations either, it simply won't work at runtime, and the objects will remain Null. You have to use JNDI lookup.
From the JBoss docs:
Lookup of EJBs #EJB annotations are
usable in servlets and JSPs, but
unfortunately, we have not yet updated
tomcat to support it. Also, Tomcat
works with the old XML format so you
cannot use XML either. So for now, you
must lookup the EJB via its global
JNDI name. This is not compliant, but
if you abstract out enough you'll be
fine.
Example:
public void init() throws ServletException
{
super.init();
try
{
InitialContext ctx = new InitialContext();
// J2EE 1.5 has not yet defined exact XML <ejb-ref> syntax for EJB3
CalculatorLocal calculator = (CalculatorLocal)ctx.lookup("tutorial/CalculatorBean/local");
setCalculator(calculator);
}
catch (NamingException e)
{
throw new RuntimeException(e);
}
}
Be sure to use the name of your EAR as the first segment in the name you are looking up (tutorial in the example above).
References:
How do I look up an ejb in jBoss
4.2?
JBoss docs
Related
I am migrating an EJB project to Spring boot project. I have successfully replaced other annotations to the spring annotation, but havving problem with SessionContext object.
My legacy code is bellow
#Resource
SessionContext sessionContext;
.....
if (some condition) {
sessionContext.setRollbackOnly();
return false;
}
For this code i am getting the following error
A component required a bean of type 'javax.ejb.SessionContext' that could not be found.
Action:
Consider defining a bean of type 'javax.ejb.SessionContext' in your configuration.
I think you'll have to use a few different functionalities.
setRollbackOnly()
Most often I have seen Session Context used for Rollbacks. In Spring, you can replace this with:
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
or annotate class with
#Transactional(rollbackFor = MyException.class)
so you can throw your exception from class to cause rollback.
getBusinessObject()
The second most commonly used feature is method to load a business object so that I can, for example, create a new transaction within a same bean. In this case you can use Self-inject:
#Lazy private final AccountService self;
and annote method with #Transactional. This, of course, solves any other cases where you need to use the power of a proxy object.
Other functionality is provided by other classes in Spring, but I think that these two are the most commonly used in the Java EE world and when migrating, one will look to replace them in Spring.
I have a third party jar in my class path which has some services and DAO's developed on top of Spring 2.0.6 and Hibernate3.2.6. I need to call some of the services and daos.
Using ClassPathXmlApplicationContext I'm able to load the application context and able to access the services and daos. Both the service and dao are following ProxyFactoryBean pattern.
Problem comes when I'm accessing a DAO which has some single valued associations.When I'm accessing associated entity I'm getting lazy initialization problem.
To solve this problem:- If it is in my own application JAR I'll be able to change the fetch type into join or in DAOImpl method I could use Hibernate.initialize().
Is there a way to avoid this problem from the stand alone code itself? Or any other way to solve this issue without modifying applicationContext.xml and DAOImpl
You need to put the caller method into one single transaction.
If you have Spring transactional environment, you can put the call of the DAO services/repositories in your own service/method which is marked as #Transactional, or if transaction support is not enabled, but you still have spring support in your application, you can just use TransactionTemplate directly, provided by spring
#Autowire
private PlatformTransactionManager txManager;
TransactionTemplate template = new TransactionTemplate(this.txManager);
template.execute( new TransactionCallback<Object>(){
public void doInTransaction(TransactionStatus status){
// work done here will be wrapped by a transaction and committed.
// status.setRollbackOnly(true) is called or an exception is thrown
}
});
Otherwise you have manually handle transactionality by your own , depending on the technologies your app is using.
I understand how to configure spring-boot and it provides a mature and sensible overriding mechanism that is documented well but I'm converting an application that gets its configuration from other source that is not in line with the spring-boot mechanism.
Ultimately the application makes properties available to the code that can be bound in using #Value("$the.prop.key:default") or used in spring xml config. The way that these properties are retrieved and bound cannot be changed.
I am trying to configure the embedded tomcat server port but the only way I can do this is using application.properties. I can change this to a different file and even change the location but I cannot change the mechanism (it has to be a file).
Looking into the spring-boot code I see it uses the notion of EmbeddedServletContainerCustomizer implementations to set these properties. Fine, I will create an implementation and set the server properties using this. But unfortunately you get 2 implementations trying to do the same thing ServerProperties and my implementation. The code orders these but because ServerProperties has not ordering it is set to the lowest priority and a low priority gets executed last and so my implementation gets overwritten.
Instead I have implemented a BeanPostProcessor:
#Named
public class SpringBootCustomConfigurator implements BeanPostProcessor {
#Value("$the.prop.key:8080")
private int port;
#Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof ServerProperties) {
ServerProperties serverProperties = (ServerProperties) bean;
serverProperties.setPort(port);
}
return bean;
}
}
This does what I need to do but it isn't a satisfactory implementation. Any thoughts?
Given that it's about a new source of external properties, I think it would be more natural to write an ApplicationContextInitializer (or ApplicationListener to listen for one of the Spring Boot events on startup) that adds a new PropertySource to your Environment in the right place. You can register initalizers with the SpringApplication or using META-INF/spring.factories.
I am using Play Framework 2.2, Hibernate as JPA provider (4.2.8.Final), Spring (4.0.1.RELEASE) and Spring Data JPA (1.4.3.RELEASE).
I am using spring to instantiate to the controllers and using context:component-scan at the application load time to collect and configure all the required dependencies(repositories etc).
The way I have configured spring with play framework is
public class Global extends GlobalSettings {
private ApplicationContext applicationContext;
#Override
public void onStart(Application arg0) {
String configLocation = Play.application().configuration().getString("spring.context.location");
applicationContext = new ClassPathXmlApplicationContext(configLocation);
}
#Override
public <A> A getControllerInstance(Class<A> type) throws Exception {
return applicationContext.getBean(type);
}
}
and relevant section in application-context.xml is
Everything works extremely good when application loads for the first time. How ever as soon as I make any changes either in views or controllers and application reloads, Spring Data Jpa breaks and complains that my models are not of managed types.
Caused by: java.lang.IllegalArgumentException: Not an managed type: class models.User
Though it is not a problem in general, restarts works fine, I would really appreciate if someone can provide any inputs to reload the applicationContext completely on play reload.
I've had the same problem. Changing Spring Data JPA 1.4.3.RELEASE to 1.4.2.RELEASE solved it. I didn't have time to look further into the problem, so I don't know what is the cause.
This project is a good starting point: https://github.com/typesafehub/play-spring-data-jpa but it uses 1.3 version of Spring Data JPA.
I'm trying to wire up Spring Data JPA objects manually so that I can generate DAO proxies (aka Repositories) - without using a Spring bean container.
Inevitably, I will be asked why I want to do this: it is because our project is already using Google Guice (and on the UI using Gin with GWT), and we don't want to maintain another IoC container configuration, or pull in all the resulting dependencies. I know we might be able to use Guice's SpringIntegration, but this would be a last resort.
It seems that everything is available to wire the objects up manually, but since it's not well documented, I'm having a difficult time.
According to the Spring Data user's guide, using repository factories standalone is possible. Unfortunately, the example shows RepositoryFactorySupport which is an abstract class. After some searching I managed to find JpaRepositoryFactory
JpaRepositoryFactory actually works fairly well, except it does not automatically create transactions. Transactions must be managed manually, or nothing will get persisted to the database:
entityManager.getTransaction().begin();
repositoryInstance.save(someJpaObject);
entityManager.getTransaction().commit();
The problem turned out to be that #Transactional annotations are not used automatically, and need the help of a TransactionInterceptor
Thankfully, the JpaRepositoryFactory can take a callback to add more AOP advice to the generated Repository proxy before returning:
final JpaTransactionManager xactManager = new JpaTransactionManager(emf);
final JpaRepositoryFactory factory = new JpaRepositoryFactory(emf.createEntityManager());
factory.addRepositoryProxyPostProcessor(new RepositoryProxyPostProcessor() {
#Override
public void postProcess(ProxyFactory factory) {
factory.addAdvice(new TransactionInterceptor(xactManager, new AnnotationTransactionAttributeSource()));
}
});
This is where things are not working out so well. Stepping through the debugger in the code, the TransactionInterceptor is indeed creating a transaction - but on the wrong EntityManager. Spring manages the active EntityManager by looking at the currently executing thread. The TransactionInterceptor does this and sees there is no active EntityManager bound to the thread, and decides to create a new one.
However, this new EntityManager is not the same instance that was created and passed into the JpaRepositoryFactory constructor, which requires an EntityManager. The question is, how do I make the TransactionInterceptor and the JpaRepositoryFactory use the same EntityManager?
Update:
While writing this up, I found out how to solve the problem but it still may not be the ideal solution. I will post this solution as a separate answer. I would be happy to hear any suggestions on a better way to use Spring Data JPA standalone than how I've solve it.
The general principle behind the design of JpaRepositoryFactory and the according Spring integration JpaRepositoryFactory bean is the following:
We're assuming you run your application inside a managed JPA runtime environment, not caring about which one.
That's the reason we rely on injected EntityManager rather than an EntityManagerFactory. By definition the EntityManager is not thread safe. So if dealt with an EntityManagerFactory directly we would have to rewrite all the resource managing code a managed runtime environment (just like Spring or EJB) would provide you.
To integrate with the Spring transaction management we use Spring's SharedEntityManagerCreator that actually does the transaction resource binding magic you've implemented manually. So you probably want to use that one to create EntityManager instances from your EntityManagerFactory. If you want to activate the transactionality at the repository beans directly (so that a call to e.g. repo.save(…) creates a transaction if none is already active) have a look at the TransactionalRepositoryProxyPostProcessor implementation in Spring Data Commons. It actually activates transactions when Spring Data repositories are used directly (e.g. for repo.save(…)) and slightly customizes the transaction configuration lookup to prefer interfaces over implementation classes to allow repository interfaces to override transaction configuration defined in SimpleJpaRepository.
I solved this by manually binding the EntityManager and EntityManagerFactory to the executing thread, before creating repositories with the JpaRepositoryFactory. This is accomplished using the TransactionSynchronizationManager.bindResource method:
emf = Persistence.createEntityManagerFactory("com.foo.model", properties);
em = emf.createEntityManager();
// Create your transaction manager and RespositoryFactory
final JpaTransactionManager xactManager = new JpaTransactionManager(emf);
final JpaRepositoryFactory factory = new JpaRepositoryFactory(em);
// Make sure calls to the repository instance are intercepted for annotated transactions
factory.addRepositoryProxyPostProcessor(new RepositoryProxyPostProcessor() {
#Override
public void postProcess(ProxyFactory factory) {
factory.addAdvice(new TransactionInterceptor(xactManager, new MatchAlwaysTransactionAttributeSource()));
}
});
// Create your repository proxy instance
FooRepository repository = factory.getRepository(FooRepository.class);
// Bind the same EntityManger used to create the Repository to the thread
TransactionSynchronizationManager.bindResource(emf, new EntityManagerHolder(em));
try{
repository.save(someInstance); // Done in a transaction using 1 EntityManger
} finally {
// Make sure to unbind when done with the repository instance
TransactionSynchronizationManager.unbindResource(getEntityManagerFactory());
}
There must be be a better way though. It seems strange that the RepositoryFactory was designed to use EnitiyManager instead of an EntityManagerFactory. I would expect, that it would first look to see if an EntityManger is bound to the thread and then either create a new one and bind it, or use an existing one.
Basically, I would want to inject the repository proxies, and expect on every call they internally create a new EntityManager, so that calls are thread safe.