My project framework is designed in such a way that I don't have access to Springs ApplicationContext. However, I would like to inject beans based on a system property. If the property is set to true, then inject all the beans, else inject none. Is this a possibility. Something like the below. BTW, Spring version is 3.0
<!-- all beans -->
<bean></bean>
<bean></bean>
<bean></bean>
<bean class ="org.springframework...PropertyPlaceHolderConfigurer>
<property name = "properties"
<value>
OBJECT_INSTANCE_ID =0
</value>
</property>
<bean>
In short the property is read using PropertyPlaceHolderConfigurer. All other beans should load based on value OBJECT_INSTANCE_ID. The property is defined in a property file located at /etc/../system.property
You can use Spring profiles to achieve this functionality:
<beans profile="dev">
<bean id="devConfig" class="<yourClassName>" />
</beans>
In the above example, the devConfig bean will be constructed only if dev profile is activated. You can activate a profile as follows:
Using annotations:
#ActiveProfiles("dev")
Using system property:
-Dspring.profiles.active=dev
If you would go for modern approaches like Java configs and Spring Boot, you can use #ConditionalOnProperty annotation that Spring Boot introduced as one of the conditional injections.
Related
First a bit of setup info:
I have a multi-tenant spring based application. The multi-tenant enabling library is an in-house developed tool where I work that I have to use. How it works is that there is an interceptor that sets in front of the servlet for the application. Upon a request hitting the servlet it loads a tenant specific spring config for "stuff" needed for the tenant specified on the url hitting the servlet.
As stated, the above is just a bit of background. Now to the issue/question:
What I want to do is to create, in the tenant configuration that is loaded, a value that I can use to inject where I need. So, is there a way I can just define a constant in a spring config and then reference it via #Value or #Resource in java code?
There will be no bean implementation behind it, it would just be purely and only a key/value that I can reference where needed in my application by name. So, something to the effect of:
<bean name="MyIdentifier">
<property name="theId" value="1001" />
</bean>
And then can I do something like?
#Value{MyIdentifier.theId}
String theId;
And have Spring be aware of and inject the value. The problem is that doing something like above Spring complains there is no implementation for the bean. Notice, no class specified for the bean. The reason I want to do this is every tenant config file will contain this bean, but the actual value will vary per tenant.
Is there some other type to use in the config to do this? If so, what schemas have to be on the config?
I am guessing I am either trying to make Spring do something not intended, or, this is so simple I cannot see it since I have stared at it too long. Anyway, thanks for the help.
You can not create bean tag in configuration file without providing class implementation. If you want to inject the value of fields, you have to go for properties file instead.
Create property file as below:
application.properties
theId=1001
Load property file in your configuration:
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="locations">
<list>
<value>classpath:application.properties</value>
</list>
</property>
</bean>
And access the property in your concrete class:
#Value("${theId}")
String theId;
In Spring, beans can be configured to be lazily initialized. Spring Batch jobs are also (Spring-managed) beans. That is, when I configure something like
<sb:job id="dummyJob" job-repository="jobRepository">
<sb:step id="dummyStep">
<sb:tasklet ref="dummyTasklet" />
</sb:step>
</sb:job>
I actually configure a new (Job-typed) bean inside the Spring container.
My issue is I really want my Job beans to be lazily initialized. As they are regular Spring-managed beans, I'd expect I can instruct the Spring context to make them lazy. This is because I have a large number of beans and there are many cases in which, during one execution of my Spring-based application, I only run one job.
But there's no lazy-init property I can set on my <sb:job... \> configuration. Is there any way I can force lazy initialization? If I configure my <beans\> root with default-lazy-init="true", will this also apply to the Job beans?
You have two options here:
Configure your job manually. This would allow you to use the regular lazy-init attributes Spring exposes.
Use the JobScope now available in Spring Batch 3. Spring Batch 3 will be available soon, but the JobScope was available in the last milestone.
Just to elaborate on Michael Minella's answer.
I had a similar requirement to lazy initialize the job repository.
I am working with Spring Batch 2.1.9.
The following is working for me.
<bean id="jobRepository"
class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean"
lazy-init="true">
<property name="dataSource" ref="jobDataSource"/>
<property name="transactionManager" ref="jobTransactionManager"/>
</bean>
Note one pitfall I had run into: do not set the databaseType i.e. avoid the following:
<property name="databaseType" value="SQLSERVER"/>
This is bad because it disable the auto-discovery of the database type and breaked my JUnits that works on H2.
I am studying Spring MVC. Today, trying to understand how implement a JDBC DAO, I have found this "Hello World" in Spring (Spring, not Spring MVC) and I begin to see it (because I think that to realize a DAO I have to create a separate Spring Project that execute the access to the data...)
http://www.tutorialspoint.com/spring/spring_hello_world_example.htm
OK, this is a standalone application and this is not a web application, so it doesn't have the web application structure (WEB-INF folder, web.xml file and the dispatcher servlet configuration file that I have in my web app)
In this example I have a Beans.xml configuration file that is used to assign unique IDs to different beans and to control the creation of objects with different values without impacting any of the Spring source files...
For example in this example I use the Beans.xml file to pass the "Hello World" message value for "message" variable and so I can print this value without impacting HelloWorld.java and MainApp.java files
<?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-3.0.xsd">
<bean id="helloWorld" class="com.tutorialspoint.HelloWorld">
<property name="message" value="Hello World!"/>
</bean>
</beans>
So I have some question for you about it:
Is this file the file that configure my Bean Factory? I think that, as well as I pass a text value as the value of a variable I could also inject a bean as a dependency of another bean.
Is it right?
In this example, can I don't use the Beans.xml file and using in place of the annotation system?
1) This Beans.xml (actually you can name it whatever you want) is a Spring configuration file. It holds a configuration metadata.
From the official Spring documentation:
5.2.1 Configuration metadata
As the preceding diagram shows, the Spring IoC container consumes a
form of configuration metadata; this configuration metadata represents
how you as an application developer tell the Spring container to
instantiate, configure, and assemble the objects in your application.
Configuration metadata is traditionally supplied in a simple and intuitive XML format, but it is not the only allowed form of configuration metadata (see the answer to your second question)
And yes, you are right: you can inject another bean as a reference.
From the official Spring documentation:
5.3 Bean overview
A Spring IoC container manages one or more beans. These beans are
created with the configuration metadata that you supply to the
container, for example, in the form of XML definitions.
Within the container itself, these bean definitions are represented as
BeanDefinition objects, which contain (among other information) the
following metadata:
A package-qualified class name: typically the actual implementation class of the bean being defined.
Bean behavioral configuration elements, which state how the bean should behave in the container (scope, lifecycle callbacks, and so
forth).
References to other beans that are needed for the bean to do its work; these references are also called collaborators or
dependencies.
Other configuration settings to set in the newly created object, for example, the number of connections to use in a bean that manages a
connection pool, or the size limit of the pool.
Simple example of using references to other beans from the official documentation:
<?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="exampleBean" class="examples.ExampleBean">
<!-- setter injection using the nested <ref/> element -->
<property name="beanOne">
<ref bean="anotherExampleBean"/>
</property>
<!-- setter injection using the neater 'ref' attribute -->
<property name="beanTwo" ref="yetAnotherBean"/>
<property name="integerProperty" value="1"/>
</bean>
<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
</beans>
2)
From the official Spring documentation:
5.2.1 Configuration metadata
...
XML-based metadata is not the only allowed form of configuration
metadata. The Spring IoC container itself is totally decoupled from
the format in which this configuration metadata is actually written.
For information about using other forms of metadata with the Spring
container, see:
Annotation-based configuration:
Spring 2.5 introduced support for annotation-based configuration
metadata.
Java-based configuration:
Starting with Spring 3.0, many features provided by the Spring
JavaConfig project became part of the core Spring Framework. Thus you
can define beans external to your application classes by using Java
rather than XML files. To use these new features, see the
#Configuration, #Bean, #Import and #DependsOn annotations.
Also read this:
Spring Without XML: The Basics of Spring Annotations vs. Spring XML Files
I created a folder /src/main/resources/ and placed this beans.xml file there:
<?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-4.3.xsd">
<bean id="employee" class="HelloSpring.Employee">
<property name="name" value="test spring"></property>
</bean>
</beans>
It worked!
I accessed it like this:
package HelloSpring;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Customer {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("./beans.xml");
Employee obj = (Employee) ctx.getBean("employee");
obj.displayName();
}
}
Is there any way to enable or disable a java bean definition in application context?
<bean id="enBean" classs="com.en.bean.BeanName">
<property name="prop1"/>
</bean>
Or, is there any way to load the bean conditionally defined in application context?
There is a new feature #Profile in spring 3.1 that would do the job
From here
Spring 3.1 introduces the concept of environment profiles. A common
use case is the setting up of beans that are different between
development, QA and production environments. A typical example is
going against a standalone DataSource in development versus looking up
the DataSource from JNDI in production. Another example is a beans
profile for profiling that can easily be turned on or off. You can add
a profile attribute on a beans element in XML or add #Profile
annotation in code. Note that a Spring bean can be assigned to
multiple profiles.
<beans profile="dev">
...
</beans>
#Profile("dev")
public class Bean {
...
}
These profiles can be activated through the spring.profiles.active
property which may be specified through an environment variable, a JVM
system property, a Servlet in web.xml or JNDI. These
profiles can also be activated through code using
Environment.setActiveProfiles(String ...). To make bean profiles work,
nested beans elements are now allowed in the Spring XML, although
constrained only at the end of the file. Note that it's recommended to
keep your bean topology as close as possible between environments, so
your application gets properly tested across environments. You also
use the Environment.containsProperty() method to search for properties
across the different property sources. This property resolution also
works for ${placeholder} variables in XML bean definitions.
Is there a way that I can configure a WebBindingInitializer for a bean in Spring XML? I can configure the binder easily using the #InitBinder command, and then settings whatever state I want on it (typically this involves setting up a validator).
An example would be...
<bean id="fooController" class="com.foobar.controller.FooController">
<property name="binder" ref="globalBinder" />
<bean/>
Where the reference is too a WebBindingInitializer that has global properties.
Not sure if this exactly meets your needs, but you can create your own WebBindingInitializer that will allow you to externalize the initialization of the WebDataBinder used by your application. See the Spring Documenation for specifics on how you setup the configuation. This technique will allow you to reuse your databinding initialization code, rather than implement it in every Controller class.