WebMvcAutoConfiguration with multiple external EntityManager - java

I have an issue in the process of migrating an existing spring web application to Spring Boot 1.5.13. I've handled almost everything, but I can't managed to have the good persistence unit injected to WebMvcAutoConfiguration. I actually have 3 different entity manager factory that are imported from the classpath (provided as .xml file by 3 different internal libraries, I have no way to change them). Each of them is splitted in this way:
<sqe-db:jpa-emf database-definition-name="db-name" embedded-datasource="false"/>
and
<bean id="transaction-mnanager-name" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="jpa-lib-name" />
</bean>
The datasources configuration is provided by tomcat at the moment, but I will externalize them to application.properties for the dev environment
After my migration, I didn't find any way to specify the right bean to WebMvcAutoConfiguration, and this is leading to the following error:
Method requestMappingHandlerMapping in org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$EnableWebMvcConfiguration required a single bean, but 3 were found:
- jpa-lib1-name1: defined in null
- jpa-lib1-name2: defined in null
- jpa-lib1-name3: defined in null
My goal at this point is to have the following configuration in place:
have the application both runnable as a SpringApplication and deployable as a WAR (and I think I already did it properly)
having a way to use Spring Boot autoconfiguration for web apps, even with multiple entity factory in the classpath
use my own datasources for the "dev" profile, but leave the tomcat one for the other environment.
my requisites are, more or less:
- minimize the changes needed to the existing application
- continue to use the .xml provided by the libraries
An easy option would be to rewrite the configuration, using a more modern annotation driven configuration, but I would prefer to stick to the existing implementation, so that I don't have to change it when a new library is released.
Any way to declare the #Primary bean without touching the existing xml file?
Any ideas, or different approaches are very welcome

After a good night of sleep, I was able to find the easiest of the solution.
I added this to my configuration class:
#Autowired
#Qualifier("name-of-default-factory")
private EntityManagerFactory entityManagerFactory;
#Bean
#Primary
public EntityManagerFactory getEntityManagerFactory() {
return entityManagerFactory;
}
And it will now have the primary bean correctly injected.

Related

Lazy load spring auto configuration

I have dependency in my spring boot project which fetches values of some properties using Spring's EnvironmentPostProcessor.
Now these properties are database credentials and not everyone has access to the credential since there is no dev environment for the db in question. I just want to change the configuration that the credentials don't get fetched on dev or local environment on application startup as that would result in a error and the application will fail to start.
Class A implements EnvironmentPostProcessor{}
I tried to use #Lazy annotation on the Class Annoteted with #ConfigurationProperties. I also tried using my own BeanFactoryPostProcessor (with #Order(HighestPrecedence) to programmatically set the A to lazy load, but it gets called before my BeanFactoryPostProcessor's postProcessBeanFactory method.
Is what I'm trying to achieve possible and am I going about it the wrong way?
#Lazy is only to be used with #Bean or #Component (Or any #Component-based annotations ex. #Service)
Take note: You can also add it to a #Configuration class, but that just means that all Beans in the class are annotated with #Lazy
#Lazy is a bit of a weird annotation in general; it should be seen as an IF possible then lazy load. If some other bean needs the lazy bean, the lazy bean will be initialized. (It's like the Pirate code, more of a guideline than an enforced rule)
Finally, marking #ConfigurationProperties with #Lazy seems a bit odd. As Spring will need these Configuration property "beans" to create the Spring Context.
However, the common use case for #Lazy is a failing database connection, preventing the application from starting. See the question if that is what you are running into.
Summary:
You can configure your repositories to be lazy-loaded with:
spring.data.jpa.repositories.bootstrap-mode=lazy
Last remark (Me just guessing)
If you wish to change properties once your application is already running, I would look at the following tutorial. It goes into manually reloading configuration and also #RefreshScope.
According to documentation EnvironmentPostProcessors must be registered via META-INF/spring.factories:
Allows for customization of the application's Environment prior to the
application context being refreshed. EnvironmentPostProcessor
implementations have to be registered in META-INF/spring.factories,
using the fully qualified name of this class as the key.
Implementations may implement the Ordered interface or use an #Order
annotation if they wish to be invoked in specific order.

Use of Bean configuration XML File

I am a new user of Spring framework. I am facing some confusion in understanding the difference between core spring framework and spring boot. As far as I understand, Spring boot is a framework which performs the initial setup automatically (like Setting up Maven dependencies and downloading the jar files) and comes with an embedded Tomcat server which makes it ready to deploy in just one click., Whereas, Spring MVC requires manual setup. All the tutorials that I watched for core spring show bean configuration using bean factory which configures the beans using a .XML file. In Spring boot, this bean configuration file is absent. My question is, what is the use of this bean configuration file? I did not find any legitimate use of this file in making a REST service with spring. I didn't see any use of the Application Context, Bean Factory in creating web application. Can someone point out how can bean factory be used in Spring web apps? Is there any fundamental difference between core spring and spring boot other than the additional components?
The Spring application context is essentially the "pool" of beans (service objects, which include controllers, converters, data-access objects, and so on) and related information that define an application; I recommend the reference introduction. In theory, you can get complicated with the context setup and have hierarchical organization and such, but in most real-world cases you just have a single plain context.
Inside this context you need to install all of the beans that provide the logic for your application. There are several possible ways to do this, but the two main ways are by providing XML files with have directives like bean (define an individual bean) or component-scan (automatically search for classes with certain annotations, including #Controller) and by using Java classes annotated with #Configuration, which can use annotations and #Bean methods.
The XML style is generally older, and newer applications mostly use Java configuration, but both provide entries that are collected into the context, and you can use both simultaneously. However, in any application, you have to provide some way of getting the registration started, and you will typically have one "root" XML file or configuration class that then imports other XML files and/or configuration classes. In a legacy web.xml-based application, you specify this in your servlet configuration file.
Spring Boot is, as you said, essentially a collection of ready-to-go configuration classes along with a mechanism for automatically detecting configurations and activating them. Even this requires a configuration root, though! This is the #EnableAutoConfiguration instruction, frequently used through its composite #SpringBootApplication. The application context and configuration mechanisms work normally once Boot finds them and pulls them in. Spring knows where to get started because you give it an explicit instruction to build a context starting with that entry point, usually with SpringApplication.run(MyApplication.class, args).
The embedded-server configuration just happens to be a particular set of configuration that is really useful and comes with one of the Boot starter packages. There's nothing there that you couldn't do in a non-Boot application.

How to avoid putting #RefreshScope on multiple beans in my application

We are externalizing configuration of our microservices (spring boot based) using spring cloud.
As per my understanding on Spring Cloud, to enable the beans loading refreshed/updated values from Config server we need to do 2 things in Spring Cloud Client:
add #RefreshScope on the beans reading values from property files
using #Value
add spring actuator to provide /refresh endpoint to
refresh the context.
Scenario:
We have 100s of classes reading values from property file using #Value.
I have to mark all these beans refresh enabled using #RefreshScope annotation.
How can I avoid putting #RefreshScope annotation on all these classes.
Is there any shortcut or spring cloud feature to get around this situation.
You may want to look into Spring Boot feature called #ConfigurationProperties. It is designed to better organize several external configuration options.
According this Github issue, it should work for spring-cloud without #RefreshScope usage.
EDIT (reaction on comment): Maybe you are missing point of #ConfigurationProperties. With this annotation, you wouldn't use it in other configuration classes. You would have dedicated class (or few classes) only for reading and providing properties. Other configuration classes would inject this configuration holder bean.
You could encapsulate your #Values into one (or several) ConfigurationService bean which is #RefreshScoped and autowire this service into your classes instead. That way you only have a small amount of request scoped beans and your services can stay singletons.

Getting bean descriptions from a spring application context xml without initializing the beans?

Is there a decent way to read a spring application context from xml without initializing the beans right away, so they can be mocked or not, before they are actually created?
Yes, I know about lazy-init, but the actual applicationContext.xml is taboo for me.
The situation is that I have to create some JUnit tests on an application which has been created in a way that puts some difficulties in the way:
the configuration file must not be altered, nor the code that is to be tested
there are a lot of beans, some of them rather complex and hard to mock
part of the test is to use as many of the beans un-mocked as possible
some of the beans implement InitializingBean, verifying the environment on initialization and throw errors when Jenkins tries to build.
new FileSystemXmlApplicationContext("config.xml") immediately initializes the beans and throws errors if not in an appropriate environment.
What I have tried:
I have tried Powermock whenNew to mock the offending beans but to do that I would have to know the class which actually creates the beans. As this class belongs to the spring framework, it may change with future versions. When using #PrepareEverythingForTest it results in an StackOverflow exception. The application is real life, not a small piece of code from some tutorial.
I also searched for something like ForceLazyFileSystemXmlApplicationContext but didn't find anything.
Pleas don't start nagging about bad design, I know about that.
You can write your own applicationContext for your testing purpose. There you need to write your own BeanFactory. In that factory you can replace some of beans with mocks.
I just remembered about an option. Evaluate if you can use spring profiles. It will allow to choose a different implementation based on profiles.
Example:
<!-- This is the default myBean -->
<beans>
<bean id="myBean" class="mypackage.MyBean" />
</beans>
<!-- This is the mocked myBean for testing purposes, it will take place when testingProfile is active -->
<beans profile="testingProfile">
<bean id="myBean" class="mypackage.MyBeanMock" />
</beans>
You can indicate which profile to use via properties or environment variables. Example, if you are using maven in your project you could run the tests as:
mvn test -Dspring.profiles.active="testingProfile"
Take a look at:
http://www.baeldung.com/spring-profiles
https://spring.io/blog/2011/02/11/spring-framework-3-1-m1-released/

Is there any way to enable or disable the Spring bean definition in applicationContext.xml file?

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.

Categories