Use of Bean configuration XML File - java

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.

Related

How does SpringBoot decrease boiler plate code?

I understand how SpringBoot saves time in other respects such as having an embedded server and starter dependencies, but how does SpringBoot reduce boiler plate code needed for an application?
Thanks
Spring Boot brings a ton of autoconfiguration classes, which create beans with default configurations, that would have been created by the developer themselves previously. An example would be beans for database access. You would have created a datasource, maybe a JdbcTemplate, connection pool etc. Now those beans are created with autoconfiguration (example: https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java), and configuration can be customized through application.properties files.
Spring boot comes with starters and through maven you can search for the required dependency and add it to your project it supports rapid development and below are some key features of spring boot
Removes boilerplate code of application setup by having embedded web
server(Tomcat) and in memory db.
Auto configuration of application context.
Automatic servlet mappings.
Embedded database support(h2)
Automatic controller mapping
You can look at Spring Boot as an opinionated distribution of Spring. It comes with sane defaults and machanisms to hide the boilerplate while still making changes to those defaults possible.
When you use annotations #SpringBootApplication, Spring boot takes care of creating all the beans required for running WebServer and injecting it using its Dependency Injection feature.
#SpringBootApplication is alone equivalent to below three annotations.
#Configuration : You can define your own configuration class to register your beans in application context.
2.#EnableAutoConfiguration : Spring automatically creates beans available on your classs path using this feature.More details are available here.
#ComponentScan : Scans the current and base package where your application class lies.
It Creates ApplicationContext which contains all the necessary beans, ServletWebServerApplicationContext is one such bean created which takes care of initializing and running a WebServer by looking for ServletWebServerFactory bean(provides the webServer) within the ApplicationContext.
There is lot more going on behind the scene. Here is a video which explains it in details.
https://youtu.be/uCE3x4-GQ0k
https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/web/servlet/context/ServletWebServerApplicationContext.html

spring boot parent for jar file

I want to create a jar file that I can add to a classpath and will basically "plug-in" to an existing spring boot application. I need it to be able to have annotations of Component, ConfigurationProperties, and all the fun things that spring boot gives you, but I want it "thin" and it will be a jar file used as part of a full spring boot web application.
I need the jar file to be externally configurable. Property files will be different for different deployments. So having a working #Configuration annotation is critical.
I look at spring-boot-starter-parent, and that has jetty, tomcat, hibernate stuff and is a huge jar file. I don't want that.
Is there a "thin" parent?
Is spring boot simply not what I want here? And I should just use a regular spring project and set my "Main" spring boot web app to do component scans to configure the jar file?
It sounds like you are trying to define your own Spring Boot Starter. That's the real power that Spring Boot gives you, the ability to include a dependency and have it auto-configure itself.
By packaging your jar the right way, Spring Boot will detect that there are configurations, components, and property files automatically. I've used this in the past for the case where I want all of my applications to log a specific way, or enforce a certain format for my REST endpoints.
The documentation gives a very thorough overview of the steps you'll need to take. But essentially, you are going to package your jar like any other (with your #Bean, #Component, #Service, and #Configuration classes in it), and provide a property file pointing to the configurations:
// Example spring.factories file
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.mycorp.libx.autoconfigure.LibXAutoConfiguration,\
com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration
Also check out the set of #ConditionalOn... annotations, they can really help with controlling what beans become active based on properties being defined, profiles being active, or dependencies being loaded.

Ease of rolling back from Spring Boot to regular Spring and viewing hybrid of Spring Context and configurations while using Spring Boot

I am assessing whether spring-boot and how I could migrate to using it.
One question I have is whether a project that uses spring boot can be converted easily back to a regular spring project which uses the traditional spring configuration files if that is required. This would be useful in my mind for a few reasons.
1) merging with legacy projects, because as I have read moving from legacy spring to spring-boot is somewhat tedious.
2) Obtaining a view of the spring application context file and webapp configuration files to understand what the actual configurations being used are.
Another question I have is regarding the lack of application-context file, is there a way to have some kind of hybrid where there is still an application-context file that can be seen? Part of my concern is that spring-boot auto configures components without us knowing and learning how they are configured and work together.
Spring Boot provides auto-configuration.
When #SpringBootApplication is encountered, it triggers a search of the CLASSPATH for a file called META-INF/spring.factories which is just a regular text file that enumerates a list of Java configuration classes. Java configuration was introduced in 2006 and then merged into Spring 3 in 2009. So it's been around for a long time. These Java configuration classes define beans in the same way that XML does. Each class is annotated with #Configuration and therein you find beans defined using methods (factory methods, or provider methods) whose return value is managed and exposed via Spring. Each such provider method is annotated with #Bean. This tells Spring to consider the method and its return value the definition of the bean.
Spring Boot tries to launch all the Java configurations it sees enumerated in that text file. It tries to launch RabbitAutoConfiguration.class, which in turn provides beans for connecting to RabbitMQ and so on. Of course, you don't want those beans in certain cases, so Spring Boot takes advantage of Spring framework 4's #Conditional mechanism to conditionally register those beans only if certain conditions are met: is a type on the CLASSPATH, is a property exposed through the environment, has there been another bean of the same type defined by the user, etc. Spring boot uses these to only create the RabbitMQ-specific beans if, for example, the dependencies that you would get from org.springframework.boot:spring-boot-starter-amqp are on the CLASSPATH. It also considers that the user may have provided a different implementation of RabbitTemplate in some othe rbean definition (be it XML or Java configuration) so it uses that if it's there.
These java configuration classes are the same sort of Java configuration classes you would write without Spring Boot. BUT... WHY? 80% of the time, the auto-configuration that Spring Boot provides is going to be as good or better than the configuration you would write yourself. There are only so many ways to configure Spring MVC, Spring Data, Spring Batch, etc., and the wager you take using Spring Boot is that the leaders and engineers on those various projects can provide the most sensible 80%-case configuration that you probably don't care to write, anyway.
So, yes you could use Spring Boot with existing applications, but you'd have to move those existing applications to Spring 4 (which is easy to do if you're using the spring-boot-starter-* dependencies) to take advantage of #Conditional. Spring Boot prefers: NO configuration, Java configuration, XML configuration, in that order.
If you have an existing application, I'd do the following:
find out what dependencies you can remove from your Gradle/Maven build and just have taken care of for you with the various spring-boot-starter- dependencies.
add #SpringBootApplication to a root component class. Eg, if your package is a.b.c, put a class Application in a.Application and annotate that with #SpringBootApplication
You can run it as a Servlet 3 application or in an embedded servlet container. It might be easier to just run in a standard servlet container as you take baby steps. Go to http://start.spring.io and make sure to choose war in the packaging drop down. Copy the ServletInitializer class and the specification from the pom.xml to ensure that your application is a .war, not a .jar. Then, once everything works on Spring Boot, rm -rf the Initializer and then revert the Maven build to a simpler .jar using the Spring Boot plugin for extra win.
If your application has lots of existing configuration, import it using #Import(OldConfig.class) or #ImportResource("old-config.xml") on the a.Application configuration class. The auto-configuration will kick in but it will see, for example, that you may have already defined a DataSource so it'll plug that in in the right places. What I like to do now is just start the application up, see if everything's OK, then start removing code in my old Java or XML configuration. Don't remove your business code, but remove things related to turning on parts of Spring. Anything that looks like #Enable..* or ..:annotation-driven/>. Restart and verify things still work. The goal is to let Spring Boot do as much of the heavy lifting as possible. Viewing the source is very handy here so you can see what Spring Boot will try to do for you. Spring Boot will log information on what #Conditional conditions evaluated to true for you. Simply provide --Ddebug=true wen you start the application to see the output. You could also export DEBUG=true then restart your IDE to run it as long as the environment variable is ivsible in your shell.

Grails app using services from spring-mvc backend

We have a fairly involved web application written using spring-mvc with a maven build system and would like to harness all the power of Grails for the front end.
So the Grails app will essentially call into the spring-mvc app's service layer to access its business logic and data.
I need some guidance with my architectural approach to this integration at a high level.
From my understanding, I will need to;
- add my spring-mvc app as a compile dependency in my BuildConfig.groovy.
- Expose the service layer objects as service beans in my conf/spring/resources.groovy and inject them into my controllers
Questions:
My spring-mvc app has lots of dependencies of its own (which it obviously has to have) which are causing lots of dependency errors. Should I be setting "transitive=false" in my config and calling all of these in my Grails app?
How should the datasource get configured? I guess I have to integrate the applicationContext of my spring-mvc app by calling it from my Grails applicationContext and hope it all bootstraps nicely?
So the Grails app will essentially call into the spring-mvc app's service layer to access its business logic and data
Can you be a bit more specific about which components of the Spring MVC you want to use from Grails, is it just the services and datasource?
I will need to add my spring-mvc app as a compile dependency in my BuildConfig.groovy
yes
Expose the service layer objects as service beans in my conf/spring/resources.groovy
Although you could make the Spring beans known to your Grails app by defining them individually in resources.groovy, this is unnecessary because you've already defined them in an Spring XML file (presumably) in the Spring MVC project.
Instead you can use the importBeans method of the BeanBuilder to import the Spring beans defined in this XML file into the Grails app. Once you've added the Spring MVC project as a dependency of your Grails app, the Spring XML file should be on your classpath, so all you need to do is add the following to resources.groovy
beans = {
importBeans('classpath:/path/to/file/applicationContext-services.xml')
}
How should the datasource get configured?
A Spring bean named dataSource defines the datasource that a Grails app uses. In a standard Grails app, this bean is created based on the configuration in DataSource.groovy. If your Spring MVC app defines a bean with this name, then this should be used instead after making the changes above. To be sure that Grails is using the datasource from your Spring MVC app rather than whatever is in DataSource.groovy, I guess you could delete the contents of the latter.

sharing spring aspect class between two webapplications

I have application consisting two web apps and EAR level jar files.
One web app (Lets say SPApp) is built using Spring and another using Struts (STApp).
I want to share the Aspect class SystemArchitecture of SPApp as defined here spring aop
6.2.3.3. Sharing common pointcut definitions
in STApp.
I have added SystemArchitecture class in EAR level jar file and gets invoked from SPApp but doesn't execute when STApp is accessed.
So then I moved the aspect class SystemArchitecture inside STApp and surprisingly it worked.
I am not sure what is going wrong when I place SystemArchitecture in EAR level lib.
Please help.
Thanks,
Hanumant
Spring AOP will not work outside spring. The Spring implementation of AOP is based on dynamic proxying where the spring bean factory will proxy advised classes to inject your pointcuts. What you are after is what's called "load time weaving" in where a java agent is used to intercept the ClassLoader and decorate advised classes when they are loaded. This is an AspectJ functionality, not a Spring AOP. Read more here: http://www.eclipse.org/aspectj/doc/released/devguide/ltw.html
Spring and AspectJ can play together as well, but it's limited to spring driven applications: http://static.springsource.org/spring/docs/3.0.0.RC2/spring-framework-reference/html/ch07s08.html
Still, if you want "true" AOP, independant of Spring then you need to go load-time weaving and AspectJ.
EDIT: may have misread your question. You say it works in your struts app only when you put your advise class in the app itself. From that I read that your Struts app is Spring driven as well. It's hard to give an answer without knowing your config. Specifically, web.xml (both), application.xml and your spring configs.

Categories