<?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.xsd">
<bean id="commonBean" class="commonBean">
</bean>
</beans>
#Configuration
#ImportResource({
"classpath:"commonConfig.xml"
})
public class CommonBeanConfiguration{
}
We have a common project as above.We are using this as jar in another project(Main Project).
We are using commonBean bean from another project(Main Project).
When we deploy Main Project(including jar of common project) on server.It works fine.
But we get "commonBean not found exception" if we try to run junit classes from Main Project. seems like beans from commonConfig.xml is
not being created in junit.
we are using spring for testing.
RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration.
Use this:
#ContextConfiguration(locations = "classpath:commonConfig.xml")
instead of #import as it loads the bean during runtime while #ContextConfiguration loads bean before invoking test cases.
Related
I am using Spring Boot 2.1.
I have some mixed configuration in my project : XML files and java classes with annotations.
We have this current configuration which works :
application.properties :
spring.profiles.active=dev, component1, component2
applicationContext-file.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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"
profile="component1">
<beans>
<bean id="myserviceimpl"
class="org.blabla.MyServiceImpl">
<property name="mydao">
<ref bean="mydao"></ref>
</property>
</bean>
</beans>
</beans>
We want to extract the component values from the spring.profiles.active property since they have nothing to do with the environment :
application.properties :
spring.profiles.active=dev
component1=true
component2=true
How can i condition the instantiation of the myserviceimpl bean inside the applicationContext-file.xml ?
I can no longer rely on the profile attribute since the spring.profiles.active property no longer includes
the values of the components.
Thanks for helping.
I haven't tried it by myself but I suggest to check the following:
Step 1
Create one XML file per profile (say, dev and prod for the sake of example):
app-config-dev.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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"
profile="dev">
<beans>
<!-- here define only beans that you want to load in __dev__ environment -->
<bean id="myserviceimpl"
class="org.blabla.MyServiceImpl">
<property name="mydao">
<ref bean="mydao"></ref>
</property>
</bean>
</beans>
</beans>
app-config-prod.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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"
profile="prod">
<beans>
<!-- here define only beans that you want to load in __production__ environment -->
<bean id="myserviceimpl"
class="org.blabla.MyServiceProdImpl">
<property name="mydao">
<ref bean="mydao"></ref>
</property>
</bean>
</beans>
</beans>
Step 2
Now in your "primary" applicationContext-file.xml instead of defining beans directly, include all the xml files that you've created during the step 1:
<import resource="classpath:app-config-dev.xml" />
<import resource="classpath:app-config-prod.xml" />
Read this thread for more details on this step if needed
Step 3
Remove the component1=true and component2=true from aplication properties, you don't need it anymore, the profile itself defines which beans should be loaded.
Update 1
Based OP's first comment:
You probably can try another option but I consider it a "low-level" solution and it requires deep understanding of how does spring loading process work under the hood.
So when spring starts it finds the definitions of beans (in xml, java config, annotations like #Component and so forth) and creates out of all this information a BeanDefinition - a metadata object that aggregates all the information about the bean (for example whether its singleton or prototype). At this point no beans are not created yet. Lets call this point in time a "Bean Definitions Done" point" (for the sake of explanations, its my term out of my head...
Then spring starts to build a graph of dependencies and starts creating beans, initializing them (Autowiring, post-construct methods, and so on) and placing them onto application context (if they're singletons).
Now, in spring there is an option to provide a hook called BeanFactoryPostProcessor that is invoked exactly at the "Bean Definitions Done" point. This is basically a java code that implements some interface and by itself is a spring bean that spring treats in a special way.
So you can implement this interface and manipulate the results of Bean factory.
Namely you can access every bean definition that spring has opened and if you think that the bean of this definition should not be created (here comes your custom logic that would check properties, whatever) - remove the bean definition from the registry:
For technical method of removing bean definitions see this thread
Here is an example of Bean Factory Post processor that actually adds a new bean although it wasn't registered
I am using spring boot project as a dependency in another non spring java project. The problem is I am getting error when spring processes #Value() annotation.
According to this article
In order to get instances of the beans managed in spring I created ClassPathXmlApplicationContext and created applicationcontext.xml,
but I am getting error from #Value("${proper}") anotation that
the resource cannot be resolved to URL because it does not exist
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"spring-application.xml"});
context.getBean("mybean");
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"
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/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.example" />
</beans>
The application.yaml is located outside the project in /opt/myapp/config/application.yaml and contains:
proper: file:/path/to/some/file/that/exists
I am expecting that spring will initialize the value of proper in component using the default application.yaml. since I can run spring boot project stand alone and it works fine.
Any Ideas?
How can I setup my camel projects to completely rely on the Spring Dependency injection system while being xml free using the maven camel run plugin. I have tried a ton of configurations, but I still seem to be stuck with a "shell context" file that just imports my java configuration file. Is there anyway to get rid of this? Note: also on latest camel version of 2.17.1
Camel Route
#Component
public class TestRoute extends SpringRouteBuilder {
#Override
public void configure() throws Exception {
from("timer://foo?repeatCount=1")
.log("Hello World");
}
}
Java Config
#Configuration
#ComponentScan("com.mcf.xml.free.route")
public class RouteJavaConfig extends CamelConfiguration {
}
Maven Camel Plugin
<plugin>
<groupId>org.apache.camel</groupId>
<artifactId>camel-maven-plugin</artifactId>
<version>${camel.version}</version>
<configuration>
<configClasses>com.mcf.xml.free.config.RouteJavaConfig</configClasses>
</configuration>
</plugin>
Plugin Context that lets it all work that I want to get rid of.
<?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: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/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean class="com.mcf.xml.free.config.RouteJavaConfig"/>
</beans>
Is there some way to have the maven camel run plugin accept the Java Config instead of a Spring Context file? Also I haven't tested this yet, but If removing this file is going to cause an issue deploying to Apache Karaf is there a way to have it configured to use my Java Config as well?
You can start your Spring Java Config application using a main class you create yourself, and then use the java-maven-exec plugin to run it. This example has no XML file at all.
There is an example as part of Apache Camel at: https://github.com/apache/camel/tree/master/examples/camel-example-spring-javaconfig
I think your scenario is a great fit for using spring boot with camel. Spring quotes:
Absolutely no code generation and no requirement for XML configuration
on their page. Spring-Boot
Here is one Spring boot-camel example you can have a look at to check: Camel-Spring Boot example
I am upgrading an application from Java7 on Glassfish 3.1.2.2, to Java8 on Glassfish 4.1. The application is packaged as an ear file, containing a jar-file with remote EJBs and Spring beans, as well as a war-file with a couple of servlets and some webservices.
There are only some minor changes done to the actual application, compared to how it was with Glassfish 3.x, the total changes made are:
Built with Java8 instead of Java7.
Deployed on Glassfish 4.1 instead of 3.1.2.2
Newer version of Hibernate
Newer version of ActiveMQ (client)
I can't see any difference between the previous ear-file and the new one (except the abovementioned lib-jars), but still when I try to deploy I get errors like this for all my EJBs:
org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type SomethingLogic with qualifiers #Default
at injection point [BackedAnnotatedField] #Inject private com.my.application.server.service.SomethingServiceSession.somethingLogic
Where SomethingService is an EJB, SomethingLogic is a Spring bean.
My EJBs are defined like this:
#Stateless
#RolesAllowed("secure")
#Interceptors(SpringBeanAutowiringInterceptor.class)
public class SomethingServiceSession implements SomethingService {
#Inject
private SomethingLogic somethingLogic; //Spring bean
SomethingLogic is an interface.
I have a beanRefContext.xml containing:
<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.xsd">
<bean id="beanFactory" class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg value="classpath*:applicationContext-glassfish.xml"/>
</bean>
</beans>
The EJB services are defined in glassfish-ejb-jar.xml, like this:
<ejb>
<ejb-name>SomethingServiceSession</ejb-name>
<ior-security-config>
<as-context>
<auth-method>USERNAME_PASSWORD</auth-method>
<realm>AD</realm>
<required>true</required>
</as-context>
</ior-security-config>
</ejb>
I have tried adding a beans.xml with the following content to the resources\META-INF folder of my EJB-project:
<?xml version="1.0"?>
<beans 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://jboss.org/schema/cdi/beans_1_0.xsd" />
No luck.
I have also tried adding #LocalBean to all my EJBs, also with no luck.
In addition, I have tried to disable CDI all together, using this command:
asadmin set configs.config.server-config.cdi-service.enable-implicit-cdi=false
This actually allows my EJB services to be deployed, but I'm suspecting that it has the not so good side effect of my webservices not being discovered, so I want to be able to deploy with CDI enabled to rule this out.
Update:
I have tried changing #Inject with #Autowired in all my non-Spring-handled classes (EJBs, webservices and servlets). Now I get the same error for actual Spring beans. It seems that Glassfish will try to look for EJB beans when encountering #Inject, no matter where they occur.
Fixed my problem by adding bean-discovery-mode="none" to my various beans.xml files.
<?xml version="1.0"?>
<beans 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://jboss.org/schema/cdi/beans_1_2.xsd"
bean-discovery-mode="none" />
I set up a application configuration file for spring, added it to the facets, and set it up according to another configuration file that works perfectly.
All of the references to the spring components are visible and seem to work, but all references to items within the xml file fail to be found.
An example is with the tasks:
<task:scheduler id="taskScheduler" />
<task:executor id="taskExecutor" pool-size="1" />
<task:annotation-driven executor="taskExecutor" scheduler="taskScheduler" />
Both taskScheduler and taskExecutor cannot be resolved. As a result, the task bean never gets set up so all of my #Scheduled annotations never work.
Setting up the factory provider for services works just fine (all #Service and #Autowired annotations work), so I am completely certain the issue is with some configuration issue in the project.
What else needs to be configured in IntelliJ for the beans to work? Why does spring not rescan the file to find references to beans?
Here is where all of the springframework beans are referenced:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd"
default-lazy-init="true">
The issue is having multiple contexts for application configuration files. To fix it, go to the configuration file in IntelliJ, then there is a section at the top where you can select which application context you want to put the context file into (Reads something like "Spring Application Context in module [your module]. File is included in [n] contexts"). Try selecting each one until the references resolve; it will remove it from the other contexts. My particular issue was that it was in the MVC context and it needed to be in the Spring Application Context.