Can I inject spring bean from JAR file? - annotations

I use Spring 3 in my project.Then I face a problem when I inject spring bean from JAR file. In JAR file, there is class like;
package test;
#Service("CommonService")
public class CommonService {
}
And i already used it like this;
package com.java.test.app;
#Service(value = "OtherService")
public class OtherService {
#Resource(name = "CommonService")
private CommonService service;
}
In my spring-beans.xml;
<context:component-scan base-package="com.java.test.app, test">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
But #Resource annotation doesn't work.Can I inject spring bean from JAR file?

If at runtime your CommonService class is on the classpath and is within the base package you specify with component-scan, then you should be good to go. Try using #Autowired instead of #Resource.

Related

SpringBoot 2.2.6 JUnit dataSource lookup error

I'm working on a big project written with java8 and SringBoot 2.2.6. The project uses Envers and, the girl builds the architecture say to me that she doesn't manage to put in the application.properties the Envers configuration. Than she do as follows:
#Configuration
public class JPAConfig {
#Autowired
private DataSource dataSource;
#Bean(name="entityManagerFactory")
public LocalSessionFactoryBean sessionFactory() throws IOException {
LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
factoryBean.setHibernateProperties(getHibernateProperties());
factoryBean.setDataSource(dataSource);
factoryBean.setPackagesToScan("it.xxxx.xxxxx.xxxxx.common.model");
return factoryBean;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
private Properties getHibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", PostgreSQL82Dialect.class.getName());
properties.put("hibernate.default_schema", "test");
properties.put("hibernate.listeners.envers.autoRegister", true);
properties.put("org.hibernate.envers.revision_field_name", "rev");
properties.put("org.hibernate.envers.revision_type_field_name", "rev_type");
properties.put("org.hibernate.envers.audit_table_prefix", "aud_");
properties.put("org.hibernate.envers.store_data_at_delete", true);
properties.put("org.hibernate.envers.audit_table_suffix", "");
return properties;
}
}
Problem is that without dataSource class name I can't start my #SpringBootTest classes and I don't know how to add it in a scenario like this (without change the configuration I mean).
I also tries to add this row inside the application.properties:
spring.profiles.active=#spring.profile#
spring.datasource.driver-class-name=org.postgresql.Driver
#JPA
spring.datasource.jndi-name=jdbc/test
But doesn't work at all..
If I run the App with JUnit I obtain this error:
org.springframework.jdbc.datasource.lookup.DataSourceLookupFailureException: Failed to look up JNDI DataSource with name 'jdbc/test'; nested exception is javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
Can you help me??
Thanks a lot
You need to register your Datasource as JNDI resource in the spring-boot embedded tomcat.
You can add it as test scope configuration.
This answer shows how to register a JNDI resource: https://stackoverflow.com/a/26005740/5230585

Arquillian Integration with WildFly 10

Can anyone please guide me on how to use Arquillian with WildFly 10. I have recently migrated my application from JBoss 7 to WildFly 10. Arquillian used to work with JBoss 7, but the same configuration is not working on WildFly 10.
I am able to integrate now, however my EJBs with JNDI names as "java:global/xyz/xyzEMFactor" is failing with following error:
Caused by: java.lang.Exception: {"WFLYCTL0180: Services with missing/unavailable dependencies" => ["jboss.naming.context.java.module.test.test.env.\"com.xyz.abc.poc.knowledge_ba‌​se.ontology.DBContex‌​tBean\".emFactory is missing [jboss.naming.context.java.global.xyz_dal.xyzpEMFactory‌​]"]} at org.jboss.as.controller.client.helpers.standalone.impl.Serve‌​rDeploymentPlanResul‌​tFuture.getActionRes‌​ult(ServerDeployment‌​PlanResultFuture.jav‌​a:134)
Following is my class:
#AccessTimeout(5 * 60 * 60 * 1000)
#StatefulTimeout(-1)
#TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class DBContextBean<T> {
#Inject
#EJB(lookup = "java:global/xyz_dal/xyzEMFactory")
private xyzEMFactory emFactory;
}
It was because, The testable war file, i was creating a jar as,
#Deployment(name = "xyz_dal", order = 3)
public static Archive<?> createDeployment() {
JavaArchive jar = ShrinkWrap.create(JavaArchive .class, "xyz_dal.jar")
.addClasses(xyzEMFactory.class, DBContextBean.class, xyzDao.class)
.addPackages(true, "com.xyz.abc.poc.entities")
.addAsResource("test-persistence.xml", "META-INF/persistence.xml")
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml").setManifest(new Asset() {
#Override
public InputStream openStream() {
// dependency management
return ManifestBuilder.newInstance()
.addManifestHeader("Dependencies", "xyz,javax.api,deployment.abc_common.jar")
.openStream();
}
});
return jar;
}
It worked when i changed it to
#Deployment(name = "xyz_dal", order = 3)
public static Archive<?> createDeployment() {
WebArchive jar = ShrinkWrap.create(WebArchive.class, "xyz_dal.war")
.addClasses(xyzpEMFactory.class, DBContextBean.class, xyzDao.class)
.addPackages(true, "com.xyz.abc.poc.entities")
.addAsResource("test-persistence.xml", "META-INF/persistence.xml")
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml").setManifest(new Asset() {
#Override
public InputStream openStream() {
// dependency management
return ManifestBuilder.newInstance()
.addManifestHeader("Dependencies", "xyz,javax.api,deployment.abc_common.jar")
.openStream();
}
});
return jar;
}
It was because when i was creating a testable jar,the container wraps the jar in a test.war, and hence the context "java:global/xyz/xyzEMFactory" was not available.
I don't know how this could work in JBoss7 but: either #EJB or #Inject, I presume #Inject, is superfluous. In my experience wildfly is sometimes more rigorous than jboss7 when looking at unclear constructs.
#Inject
#EJB(lookup = "java:global/xyz_dal/xyzEMFactory")
xyzEMFactory emFactory;
CDI can't inject ejbs. What we do sometimes is:
#Produces
#EJB(lookup = "java:global/xyz/xyzEMFactory")
xyzEMFactory emFactory;
Then you can use at other places
#Inject
xyzEMFactory emFactory;
because the ejb-injected bean can be used as Producer-Field.

how to inject the multiple bean in to single referenced variable dynamically using spring annotation

I have interface A.java and 3 classes which are implementing A.java interface named B.java, C.java and D.java. Now i am try to inject the bean like this.
interface A{}
#Component
#Scope("request")
class B implements A{
//......
}
#Component
#Scope("request")
class C implements A{
//.....
}
#Component
#Scope("request")
class D implements A{
}
class Implementation{
#Autowired
public A obj;
#Autowired
private BeanFactory beanFactory;
String[] beans = {"B","C","D"}; //actually these are coming from database in my case
for(String beanName : beans){
obj = (A)beanFactory.getBean(beanName);
....//calling some method of particular bean class
}
}
It is showing Error message something: "Unique bean not found: contains multiple beans["B","C","D"]".
If I am configuring these beans in XML file, it is working fine but I don't want to use xml config
How to solve this problem Using spring Annonantion??
It seems to me that the problem is with the Autowired annotation, because it'll do the injection by type, and the type of your variable is A, so It will be difficult to decide which bean to actually inject, B, C or D.
Try to use Resource annotation which decide to inject by name. Or instead just add Qualifier annotation.
Look here for further explanation:
Difference between #Qualifier and #Resource

Is it possible to annotate class constructor in Kotlin

Clarification
This questions was asked before kotlin hit version 1.0. Language syntax in example is obsolete now, please follow official docs.
I'm playing with kotlin and spring DI.
I want to use constructor-based dependency injection, so I need to annotate the constructor.
I tried following approach:
Configuration
Import(javaClass<DataSourceConfig>())
public open class AppConfig(dataSource: DataSource) {
private val dataSource: DataSource
Autowired {
this.dataSource = dataSource
}
}
Configuration
public open class DataSourceConfig {
Bean
public open fun dataSource(): DataSource {
// source omitted
}
}
But it doesn't work. Is it even possible to annotate constructor in kotlin?
P.S. I'm using Kotlin M10.1 and Spring 4.1.4
UPDATE:
Annotating constructor is possible in kotlin. The problem was that it's not allowed to use constructor-based DI for #Configuration
Hrm, I think the syntax has changed radically since this question was posted. The current way (according to the docs) is to add the keyword constructor between your class name and arguments and annotate that, i.e.
public class AppConfig #Configuration constructor(dataSource: DataSource) {
//...
}
Try to write:
Configuration
public open class AppConfig [Import(javaClass<DataSourceConfig>())] (dataSource: DataSource) {
//...
}
This syntax works for me:
Configuration
Import(javaClass<DataSourceConfig>())
public open class AppConfig {
private val dataSource: DataSource
Autowired constructor(dataSource: DataSource){
this.dataSource = dataSource
}
}

Spring bean loading issue in BIRT designer

I have an issue with Spring not loading beans correctly when run from a script in a BIRT Scripted Data Source, but running OK on its own.
Here's a minimal test case:
The spring bean:
package test;
import org.springframework.stereotype.Component;
#Component
public class TestComponent { }
The context provider:
package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringContextHolder {
private static ApplicationContext ac;
public static ApplicationContext getApplicationContext() {
if( ac == null ) {
ac = new ClassPathXmlApplicationContext("classpath:beans.xml");
}
return ac;
}
}
beans.xml:
<beans .......>
<context:component-scan base-package="test"></context:component-scan>
<context:annotation-config />
</beans>
And finally the test program which is a simple Eclipse java project having all spring and related jars and the test.jar from above in its build path:
public class cltest {
public static void main(String[] args ) throws BeansException {
System.out.println(test.SpringContextHolder.getApplicationContext().getBean("testComponent"));
}
}
This program runs fine and delivers the bean. But when I run the same jars in BIRT designer (4.3.0) by setting them in the Report classpath preferences, I get an exception:
A BIRT exception occurred. See next exception for more information.
Wrapped org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class: URL [jar:file:/C:/Users/xxx/.m2/repository/test/test/0.0.1-SNAPSHOT/test-0.0.1-SNAPSHOT.jar!/test/SpringContextHolder.class]; nested exception is java.lang.ArrayIndexOutOfBoundsException: 6
The script source is simply:
importPackage(Packages.test);
ts = SpringContextHolder.getApplicationContext().getBean("testComponent");
The exception results from org.springframework.asm.ClassReader where a readShort violates some array boundaries.
Spring version is 3.2.3 RELEASE, Oracle Java 7u25, BIRT Designer 4.3.0.
Can anyone explain what the difference between the two running scenarios is? Probably some class loader issues when the jars are loaded by the eclipse runtime?