Is it possible to mix spring xml configuration with java - java

I am using spring framework 4.1.4
I have JBoss5XmlWebApplicationContext as my contextClass reading xml configuration.
I want to add #Configuration class to be read aside from the xml.
Is this possible? How to do it?

Yes, Its possible. One way I know is using springboot classes. I am using MySpringConfiguration class to declare beans using #Configuration and MySpringConfig.xml for xml based bean configuration. I am able to load beans from the context coming from both sources.
Check below code:
public static void main(String[] args) {
Resource res = new FileSystemResource("E:\\MySpringConfig.xml");
SpringApplication app = new SpringApplication(MySpringConfiguration.class,res);
ApplicationContext ctx = app.run("");
MyXMLBean myXMLBean = (MyXMLBean)ctx.getBean("myNewBean"); // From XML file...
GeData geData= (GeData)ctx.getBean("geData"); // From Java Configuration ...
....
Configuration class goes like this
#Configuration
public class MySpringConfiguration {
#Bean
public GeData geData(){
return new GeData();
}
Hope this helps...

Related

Other ways to create a Bean Factory in Spring Framework

I understand the difference between a BeanFactory and an ApplicationContext.
I am also aware that a BeanFactory instance can be created from xml files, which reside in the classpath or anywhere else in the file system. So, an XMLBeanFactory instance is created in such cases.
At the same time, I was digging into BeanFactory documentation and stumbled upon this.
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/BeanFactory.html
Normally a BeanFactory will load bean definitions stored in a configuration source (such as an XML document), and use the org.springframework.beans package to configure the beans. However, an implementation could simply return Java objects it creates as necessary directly in Java code. There are no constraints on how the definitions could be stored: LDAP, RDBMS, XML, properties file, etc. Implementations are encouraged to support references amongst beans (Dependency Injection).
So, does this mean that the bean definition can be in non-XML format as well? viz, LDAP, RDBMS, properties file etc? If yes, please provide an snippet of it. I am exclusively looking for BeanFactory only and not any ApplicationContext implementations.
How to load an ApplicationContext which is a BeanFactory on steriods is explained in this blog.
public class SpringContextsApplication {
public static void main(String[] args) throws Exception {
GenericApplicationContext contextFromProperties =
new GenericApplicationContext();
BeanDefinitionReader reader =
new PropertiesBeanDefinitionReader(contextFromProperties);
reader.loadBeanDefinitions("classpath:application-context.properties");
contextFromProperties.refresh();
doGreeting(contextFromProperties);
contextFromProperties.stop();
}
private static void doGreeting(ApplicationContext ctx) {
Greeter greeter = ctx.getBean(Greeter.class);
Person person = ctx.getBean(Person.class);
greeter.greet(person);
}
}
Where there is a GenericApplicationContext one could also use a DefaultListableBeanFactory instead and achieve the same result.
public class SpringContextsApplication {
public static void main(String[] args) throws Exception {
GenericApplicationContext contextFromProperties =
new DefaultListableBeanFactory();
BeanDefinitionReader reader =
new PropertiesBeanDefinitionReader(contextFromProperties);
reader.loadBeanDefinitions("classpath:application-context.properties");
doGreeting(contextFromProperties);
contextFromProperties.stop();
}
private static void doGreeting(BeanFactory ctx) {
Greeter greeter = ctx.getBean(Greeter.class);
Person person = ctx.getBean(Person.class);
greeter.greet(person);
}
}
To load bean definitions one needs a BeanDefinitionReader for that specific implementation you want to use. Here that is property files but you could write a BeanDefinitionReader for LDAP, JDBC, YAML etc. as well.
Spring supports out-of-the-box
XML
Properties (Deprecated as of Spring 5.3, propably removed in Spring 6)
Groovy
Java Classes
JDBC (Purely as an exampled, deprecated in 5.3 and removed in Spring 6)
However you can create whatever implementation you like if you need.

Context Configuration Not loading beans and throwing null pointer exception

Is there a way we can load spring.xml file in a java class and load all the beans.
For example:
#ContextConfiguration(locations = {"classpath*: spring.xml"})
public class springtest {
#Autowired
private PayloadRequest payloadRequest ;
}
#Component
public class PayloadRequest (){
}
You can use
#ImportResource("Path to file") this is used for importing xml configuration
#Import({java classes}) this is used for importing java configuration
Here is link for official documentation:
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/ImportResource.html
To load XML configure beans into the application context use #ImportResource
The recommended way is to create a separate configuration class to load this xml bean definition file.
#Configuration
#ImportResource({"classpath*:applicationContext.xml"})
public class XmlConfiguration {
}
load multiple configs
#Configuration
#Import({ AppConfigOthers.class }) //loads another JavaConfig
#ImportResource("classpath:/config/spring-web-servlet.xml")
public class AppConfigCore {
//...
}
By java code Just load in main method
ApplicationContext APPLICATION_CONTEXT = new ClassPathXmlApplicationContext("/spring/context/application-context.xml");

EnableWebMvc throws ServletException: Could not resolve view with name

Playing around with Spring Boot + MVC with static HTML pages, while noticed this thing:
Firstly, what I have:
Index controller:
#Controller
public class IndexController {
#RequestMapping("/")
public String index() {
return "index.html";
}
#RequestMapping("/{path:[^\\.]+}/**")
public String forward() {
return "forward:/";
}
}
The Html file is:...\src\main\resources\static\index.html
So when my main application class is:
#SpringBootApplication
public class MyApplication extends WebMvcConfigurerAdapter {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
Everything works well and in default path: localhost:8080\ I get index.html page content
But if I annotate Application class with #EnableWebMvc
#SpringBootApplication
#EnableWebMvc
public class MyApplication extends WebMvcConfigurerAdapter {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
I get exception: javax.servlet.ServletException: Could not resolve view with name 'index.html' in servlet with name 'dispatcherServlet'
But according to this spring doc it is a valid configuration.
Maybe someone can explain me why? Do I understand something wrong?
According to spring-boot's docs
The auto-configuration adds the following features on top of Spring’s defaults:
Static index.html support.
...
If you want to keep Spring Boot MVC features, and you just want to add
additional MVC configuration (interceptors, formatters, view
controllers etc.) you can add your own #Configuration class of type
WebMvcConfigurerAdapter, but without #EnableWebMvc. If you wish to
provide custom instances of RequestMappingHandlerMapping,
RequestMappingHandlerAdapter or ExceptionHandlerExceptionResolver you
can declare a WebMvcRegistrationsAdapter instance providing such
components.
So by adding #EnableWebMvc you just disable what spring-boot autoconfiguring for you. Namely static index.html support.
Actually I think when you choose to use spring boot you should use the default config of spring Boot. It means you just have to edit the file application.properties. Now if you use spring mvc, you have to provide your own servlet. So I think mixing up the to is not a good idea. Either you use spring Boot wiht no much config to do or you use spring mvc and you make all the necessary config.
According to Spring Boot MVC structure, you should locate your html file in the templates folder. Then will be visible for Spring Boot
src\main\resources\templates\index.html

Spring data multiple datasources from multiple files

I have 2 (or more) different configuration properties file located in the project and I want to load them for different datasources.
I tried to do as following:
#Bean
#ConfigurationProperties(locations = {"#{myconfigroot.getRootFolder()}/datasource1.properties"}
public static DataSource getFirstDatasource() {
return DataSourceBuilder.create().build();
}
But obviously this won't work as the ConfigurationProperties annotation locations property doesn't go through the spEL. (Or may be I write it wrong?) myconfigroot.getRootFolder() is a static method which returns the path to the datasource1.properties.
Please advice. Thanks.
===== Edited =======
I believe this is a common problem when somebody want their application want to load different configuration files. Due to some reasons the file location and name can't be put in the startup script or command line, or, the path can only be determined in runtime, that would require spring to load them during the bean creation.
I tried once using PropertySourcePlaceHolderConfigurer but seems not work either.
Anybody can share some lights?
Latest Spring boot (version 1.3.5) doesn’t support SpEL in this case.
See JavaDoc of annotation #ConfigurationProperties
Note that contrary to {#code #Value}, SpEL expressions are not
evaluated since property values are externalized.
I found a way to customize Spring boot default behavior as follows:
For example, I have database.properties file in somewhere, for some reason I cannot get the location before runtime.
username=mike
password=password
Accordingly, define POJO mapping to properties:
#Component
#ConfigurationProperties(locations = "myConfiguration")// myConfiguration is customized placeholder
public class MyProperties{
String username;
String password;
//Getters, Setters…
}
Then, to extend default StandardEnvironment:
public class MyEnvironment extends StandardEnvironment {
#Override
public String resolvePlaceholders(String location) {
if (location.equals("myConfiguration")) {
//Whatever you can do, SpEL, method call...
//Return database.properties path at runtime in this case
return getRootFolder() + "datasource.properties";
} else {
return super.resolvePlaceholders(text);
}
}
}
Last, apply it in Spring boot main method entry:
#SpringBootApplication
public class MyApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
new SpeedRestApplication()
.configure(new SpringApplicationBuilder(SpeedRestApplication.class).environment(new MyEnvironment()))//Replace default StandardEnvironment
.run(args);
}
}
Once Spring boot starts up, the MyProperties bean name and password fields are injected from database.properties. Then you could wire the MyProperties bean to other beans as configuration.
Hope it helps!
I finally got it work by using the following mechanism:
public class DatasourcePostProcessor implements EnvironmentPostProcessor {
#Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
Properties p = new Properties();
p.load(new FileInputStream(new File(getRootFolder() + "/datasource1.properties")));
Map<String, Object> propMap = new HashMap<>();
for (Map.Entry<Object, Object> entry : p.entrySet()) {
propMap.put(entry.getKey().toString(), entry.getValue());
}
MapPropertySource source = new MapPropertySource("datasource1", propMap);
environment.getPropertySources().addLast(source);
}
}
and register the environment post processor into the spring.factories:
org.springframework.boot.env.EnvironmentPostProcessor=com.myorg.test.DatasourcePostProcessor
Anyway, hope this helps people and accept the first anwer as it enlight me. Also post the following references from the google search that found during research:
Where I found how to wire the property source with the environment: https://github.com/spring-projects/spring-boot/issues/4595
Where I found how to load the customized properties file: How to configure a custom source to feed Spring Boot's #ConfigurationProperties

How to extend spring by configuring spring xml

In a Spring 4 application, we are extending PropertySourcesPlaceholderConfigurer to do some custom task during resolving properties.
To register our new class (MyPropertyConfigurer) o Spring we use the following class:
#Configuration
public class AppConfig {
#Bean
public static PropertySourcesPlaceholderConfigurer
propertySourcesPlaceholderConfigurer() {
return new MyPropertyConfigurer();
}
}
As a matter of curiosity, can I add my new bean to Spring with spring.xml instead of using the #Configuration annotation?
I had the same problem, my problem was fixed simply with placing the bean of my class in my Springbeans.xml file like below:
<beans:bean class="MyPropertyConfigurer"/>
You can very well use a combination of both Spring based xml and java based config in your spring application.
You have to use
#ImportResource({"classpath:sampleapp.xml"})
along with
#Configuration
Look at the sample post below which explains it:
Mixing xml and java config with spring

Categories