Chapter 1: Getting Started With Spring Framework: Section 1.1: Setup (XML Configuration)
Chapter 1: Getting Started With Spring Framework: Section 1.1: Setup (XML Configuration)
Framework
Version Release Date
5.0.x 2017-10-24
4.3.x 2016-06-10
4.2.x 2015-07-31
4.1.x 2014-09-14
4.0.x 2013-12-12
3.2.x 2012-12-13
3.1.x 2011-12-13
3.0.x 2009-12-17
2.5.x 2007-12-25
2.0.x 2006-10-04
1.2.x 2005-05-13
1.1.x 2004-09-05
1.0.x 2003-03-24
1. Investigate Spring Boot to see if that would better suit your needs.
2. Have a project set up with the correct dependencies. It is recommended that you are using Maven or Gradle.
3. create a POJO class, e.g. Employee.java
4. create a XML file where you can define your class and variables. e.g beans.xml
5. create your main class e.g. Customer.java
6. Include spring-beans (and its transitive dependencies!) as a dependency.
Employee.java:
package com.test;
beans.xml:
</beans>
Customer.java:
package com.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
This is a self-contained running example including/showcasing: minimum dependencies needed, Java Configuration,
Bean declaration by annotation and Java Configuration, Dependency Injection by Constructor and by Property, and
Pre/Post hooks.
Dependencies
1. spring-core
2. spring-context
3. spring-beans
4. spring-aop
5. spring-expression
6. commons-logging
Main Class
Starting from the end, this is our Main class that serves as a placeholder for the main() method which initialises the
Application Context by pointing to the Configuration class and loads all the various beans needed to showcase
particular functionality.
package com.stackoverflow.documentation;
import org.springframework.context.ApplicationContext;
The configuration class is annotated by @Configuration and is used as a parameter in the initialised Application
Context. The @ComponentScan annotation at the class level of the configuration class points to a package to be
scanned for Beans and dependencies registered using annotations. Finally the @Bean annotation serves as a bean
definition in the configuration class.
package com.stackoverflow.documentation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.stackoverflow.documentation")
public class AppConfig {
@Bean
public BeanDeclaredInAppConfig beanDeclaredInAppConfig() {
return new BeanDeclaredInAppConfig();
}
The @Component annotation serves to demarcate the POJO as a Spring bean available for registration during
component scanning.
@Component
public class BeanDeclaredByAnnotation {
Notice that we don't need to annotate or otherwise mark our POJO since the bean declaration/definition is
happening in the Application Configuration class file.
Constructor Injection
Notice that the @Autowired annotation is set at the constructor level. Also notice that unless explicitely defined by
name the default autowiring is happening based on the type of the bean (in this instance BeanToBeInjected).
package com.stackoverflow.documentation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class BeanConstructorInjection {
@Autowired
public BeanConstructorInjection(BeanToBeInjected dependency) {
this.dependency = dependency;
}
Property Injection
Notice that the @Autowired annotation demarcates the setter method whose name follows the JavaBeans standard.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class BeanPropertyInjection {
@Autowired
public void setBeanToBeInjected(BeanToBeInjected beanToBeInjected) {
this.dependency = beanToBeInjected;
}
We can intercept initialisation and destruction of a Bean by the @PostConstruct and @PreDestroy hooks.
package com.stackoverflow.documentation;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Component
public class BeanPostConstructPreDestroy {
@PostConstruct
public void pre() {
System.out.println("BeanPostConstructPreDestroy - PostConstruct");
}
@PreDestroy
public void post() {
System.out.println("BeanPostConstructPreDestroy - PreDestroy");
}
}
Which is treated as boilerplate code as every programmer write the same code. So for simplicity the framework
takes care of boilerplate logic and the programmer has to write only business logic. So by using Spring framework
we can develop projects rapidly with minimum lines of code, without any bug, the development cost and time also
reduced.
Strut is a framework which provide solution to web aspects only and struts is invasive in nature. Spring has many
features over struts so we have to choose Spring.
1. Spring is Noninvasive in nature: That means you don't need to extend any classes or implement any
interfaces to your class.
2. Spring is versatile: That means it can integrated with any existing technology in your project.
3. Spring provides end to end project development: That means we can develop all the modules like business
layer, persistence layer.
4. Spring is light weight: That means if you want to work on particular module then , you don't need to learn
complete spring, only learn that particular module(eg. Spring Jdbc, Spring DAO)
5. Spring supports dependency injection.
6. Spring supports multiple project development eg: Core java Application, Web Application, Distributed
Application, Enterprise Application.
7. Spring supports Aspect oriented Programming for cross cutting concerns.
So finally we can say Spring is an alternative to Struts. But Spring is not a replacement of J2EE API, As Spring
supplied classes internally uses J2EE API classes. Spring is a vast framework so it has divided into several modules.
No module is dependent to another except Spring Core. Some Important modules are
1. Spring Core
2. Spring JDBC
3. Spring AOP
4. Spring Transaction
5. Spring ORM
6. Spring MVC
1. Spring Core
2. Spring AOP
3. Spring JDBC
4. Spring Transaction
5. Spring ORM
6. Spring MVC
All the modules of Spring are independent of each other except Spring Core. As Spring core is the base module, so
in all module we have to use Spring Core
Spring Core
Spring Core talking all about dependency management.That means if any arbitrary classes provided to spring then
Spring can manage dependency.
What is a dependency:
From project point of view, in a project or application multiple classes are there with different functionality. and
each classes required some functionality of other classes.
Example:
class Engine {
class Car {
Here class Engine is required by class car so we can say class engine is dependent to class Car, So instead of we
managing those dependency by Inheritance or creating object as fallows.
By Inheritance:
class Engine {
class Engine {
class Car {
So instead of we managing dependency between classes spring core takes the responsibility dependency
management. But Some rule are there, The classes must be designed with some design technique that is Strategy
design pattern.
//Interface
package com.sdp.component;
package com.sdp.component;
package com.sdp.component;
//Component classe
package com.sdp.service;
import com.sdp.component.Courier;
package com.sdp.util;
import java.io.IOException;
import java.util.Properties;
import com.sdp.component.Courier;
props=new Properties();
try {
}
public static Object getInstance(String logicalclassName)
{
Object obj = null;
String originalclassName=props.getProperty(logicalclassName);
try {
obj=Class.forName(originalclassName).newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return obj;
}
//properties file
BlueDart.class=com.sdp.component.BlueDart
Dtdc.class=com.sdp.component.Dtdc
FlipKart.class=com.sdp.service.FlipKart
//Test class
package com.sdp.test;
import com.sdp.component.Courier;
import com.sdp.service.FlipKart;
import com.sdp.util.ObjectFactory;
If we write this code then we can manually achieve loose coupling,this is applicable if all the classes want either
BlueDart or Dtdc , But if some class want BlueDart and some other class want Dtdc then again it will be tightly
coupled, So instead of we creating and managing the dependency injection Spring core takes the responsibility of
creating and managing the beans, Hope This will helpful, in next example we wil see the !st application on Spring
core with deitals
Literal expressions
Supported types include strings, dates, numeric values (int, real, and hex), boolean and null.
Inline list
"#{1,2,3,4}" //list of number
"#{{'a','b'},{'x','y'}}" //list of list
Inline Maps
"#{name:'Nikola',dob:'10-July-1856'}"
"#{name:{first:'Nikola',last:'Tesla'},dob:{day:10,month:'July',year:1856}}" //map of maps
Invoking Methods
"#{'abc'.length()}" //evaluates to 3
"#{f('hello')}" //f is a method in the class to which this expression belongs, it has a string
parameter
I am working with an Oracle database, I've attempted to create an example that should work for other databases,
my Oracle example details issues with Oracle.
This example assumes your procedure has a single output parameter that is a cursor; you will need to adjust your
declareParameters to match your procedure.
@Service
public class MyService() {
@Autowired
private DataSource dataSource;
Assuming your procedure output parameter is ref cursor, you will get this exception.
Supporting OracleTypes
You may only need to do this if you have certain column types in your data.
The next issue I encountered was that proprietary Types such as oracle.sql.TIMESTAMPTZ caused this error in
SqlRowSetResultSetExtractor:
Invalid SQL type for column; nested exception is java.sql.SQLException: Invalid SQL type for column
package com.boost.oracle;
import oracle.jdbc.rowset.OracleCachedRowSet;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.support.rowset.ResultSetWrappingSqlRowSet;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* OracleTypes can cause {@link org.springframework.jdbc.core.SqlRowSetResultSetExtractor}
* to fail due to a Oracle SQL type that is not in the standard {@link java.sql.Types}.
*
* Also, types such as {@link oracle.sql.TIMESTAMPTZ} require a Connection when processing
* the ResultSet; {@link OracleCachedRowSet#getConnectionInternal()} requires a JNDI
* DataSource name or the username and password to be set.
*
* For now I decided to just set the password since changing SpringBoot to a JNDI DataSource
* configuration is a bit complicated.
*
* Created by Arlo White on 2/23/17.
*/
public class OracleSqlRowSetResultSetExtractor implements ResultSetExtractor<SqlRowSet> {
@Override
public SqlRowSet extractData(ResultSet rs) throws SQLException, DataAccessException {
OracleCachedRowSet cachedRowSet = new OracleCachedRowSet();
// allows getConnectionInternal to get a Connection for TIMESTAMPTZ
cachedRowSet.setPassword(oraclePassword);
cachedRowSet.populate(rs);
return new ResultSetWrappingSqlRowSet(cachedRowSet);
}
Certain Oracle types require a Connection to obtain the column value from a ResultSet. TIMESTAMPTZ is one of
these types. So when rowSet.getTimestamp(colIndex) is called, you will get this exception:
Caused by: java.sql.SQLException: One or more of the authenticating RowSet properties not set at
oracle.jdbc.rowset.OracleCachedRowSet.getConnectionInternal(OracleCachedRowSet.java:560) at
oracle.jdbc.rowset.OracleCachedRowSet.getTimestamp(OracleCachedRowSet.java:3717) at
org.springframework.jdbc.support.rowset.ResultSetWrappingSqlRowSet.getTimestamp
If you dig into this code, you will see that the OracleCachedRowSet needs the password or a JNDI DataSource name
to get a Connection. If you prefer the JNDI lookup, just verify that OracleCachedRowSet has DataSourceName set.
So in my Service, I Autowire in the password and declare the output parameter like this:
Foo Class:
Interface:
@Component(value="FooNameValidator")
public class FooNameValidator implements FooValidator {
@Override
public Foo validate(Foo foo) {
//Validation logic goes here.
}
}
@Component(value="FooEmailValidator")
public class FooEmailValidator implements FooValidator {
@Override
public Foo validate(Foo foo) {
//Different validation logic goes here.
}
}
You can now autowire these validators individually or together into a class.
Interface:
Class:
@Service
public class FooServiceImpl implements FooService {
/** Autowire all classes implementing FooValidator interface**/
@Autowired
@Override
public void handleFoo(Foo foo) {
/**You can use all instances from the list**/
for(FooValidator validator : allValidators) {
foo = validator.validate(foo);
}
}
}
It's worth noting that if you have more than one implementation of an interface in the Spring IoC container and
don't specify which one you want to use with the @Qualifier annotation, Spring will throw an exception when
trying to start, because it won't know which instance to use.
1: This is not the right way to do such simple validations. This is a simple example about autowiring. If you want an
idea of a much easier validation method look up how Spring does validation with annotations.
Class:
@Service
public class FooServiceImpl implements FooService {
@Override
public int doSomething() {
//Do some stuff here
return 0;
}
}
It should be noted that a class must implement an interface for Spring to be able to autowire this class. There is a
method to allow Spring to autowire stand-alone classes using load time weaving, but that is out of scope for this
example.
You can gain access to this bean in any class that instantiated by the Spring IoC container using the @Autowired
annotation.
Usage:
@Autowired([required=true])
The @Autowired annotation will first attempt to autowire by type, and then fall back on bean name in the event of
ambiguity.
Constructor injection:
Field injection:
Setter injection:
@Autowired
public void setFooService(FooService fooService) {
this.fooService = fooService;
}
}
Configuration:
@Configuration
public class ExampleConfig {
@Bean
public FactoryBean<String> fromFactory() {
return new ExampleFactoryBean();
}
}
To get the actual FactoryBean, use the ampersand prefix before the bean's name:
Please note that you can only use prototype or singleton scopes - to change the scope to prototype override
isSingleton method:
Note that scoping refers to the actual instances being created, not the factory bean itself.
When JavaConfig encounters such a method, it will execute that method and register the return value as a bean
within a BeanFactory. By default, the bean name will be that of the method name.
1. Using Java based Configuration: In Configuration file we need to declare bean using @bean annotation
@Configuration
public class AppConfig {
@Bean
public TransferService transferService() {
return new TransferServiceImpl();
}
}
2. Using XML based configuration: For XML based configuration we need to create declare bean in application
configuration XML i.e.
<beans>
<bean name="transferService" class="com.acme.TransferServiceImpl"/>
</beans>
@Component("transferService")
public class TransferServiceImpl implements TransferService {
Now all three beans with name transferService are available in BeanFactory or ApplicationContext.
Foo Class:
Interface:
@Component(value="FooNameValidator")
public class FooNameValidator implements FooValidator {
@Override
public Foo validate(Foo foo) {
//Validation logic goes here.
}
}
@Component(value="FooEmailValidator")
public class FooEmailValidator implements FooValidator {
@Override
public Foo validate(Foo foo) {
//Different validation logic goes here.
}
}
Interface:
Class:
@Autowired
@Qualifier("FooEmailValidator")
private FooValidator emailValidator;
@Override
public void handleFoo(Foo foo) {
/**You can use just one instance if you need**/
foo = nameValidator.validate(foo);
}
}
It's worth noting that if you have more than one implementation of an interface in the Spring IoC container and
don't specify which one you want to use with the @Qualifier annotation, Spring will throw an exception when
trying to start, because it won't know which instance to use.
1: This is not the right way to do such simple validations. This is a simple example about autowiring. If you want an
idea of a much easier validation method look up how Spring does validation with annotations.
Interface:
@Component
public class FooValidator implements GenericValidator<Foo> {
@Override
public Foo validate(Foo foo) {
//Logic here to validate foo objects.
}
}
@Component
public class BarValidator implements GenericValidator<Bar> {
@Override
public Bar validate(Bar bar) {
You can now autowire these validators using type parameters to decide which instance to autowire.
Interface:
Class:
@Service
public class FooServiceImpl implements FooService {
/** Autowire Foo Validator **/
@Autowired
private GenericValidator<Foo> fooValidator;
@Override
public void handleFoo(Foo foo) {
foo = fooValidator.validate(foo);
}
}
Approaches #3 and #4 are generally discouraged, since they strongly tie an app to Spring framework. Thus, they
are not covered in this example.
Java Classes
XML
Java Classes
@Component
public class WindowGenerator {
@Lookup
protected Window createNewWindow() {
throw new UnsupportedOperationException();
}
}
Java configuration
@Configuration
@ComponentScan("somepackage") // package where WindowGenerator is located
public class MyConfiguration {
@Bean
@Lazy
@Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public Window window() {
return new Window();
}
}
Java Classes
Java configuration
@Configuration
public class MyConfiguration {
@Bean
@Lazy
@Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public Window window() {
return new Window();
}
@Bean
public WindowGenerator windowGenerator(){
return new WindowGenerator() {
@Override
protected Window createNewWindow(){
return window();
}
};
}
}
Java classes
XML
The same approaches can be used for other scopes as well (e.g. for injection a request-scoped bean into singleton).
No additional setup is required to declare and access web-scoped beans in Spring Web MVC environment.
XML Configuration
<bean id="myRequestBean" class="OneClass" scope="request"/>
<bean id="mySessionBean" class="AnotherClass" scope="session"/>
<bean id="myApplicationBean" class="YetAnotherClass" scope="application"/>
<bean id="myGlobalSessionBean" class="OneMoreClass" scope="globalSession"/>
@Bean
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public OneClass myRequestBean() {
return new OneClass();
}
@Bean
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public AnotherClass mySessionBean() {
return new AnotherClass();
}
@Bean
@Scope(value = WebApplicationContext.SCOPE_APPLICATION, proxyMode =
ScopedProxyMode.TARGET_CLASS)
public YetAnotherClass myApplicationBean() {
return new YetAnotherClass();
}
@Bean
@Scope(value = WebApplicationContext.SCOPE_GLOBAL_SESSION, proxyMode =
ScopedProxyMode.TARGET_CLASS)
public OneMoreClass myGlobalSessionBean() {
return new OneMoreClass();
}
}
@Bean
@SessionScope
public AnotherClass mySessionBean() {
return new AnotherClass();
}
@Bean
@ApplicationScope
public YetAnotherClass myApplicationBean() {
return new YetAnotherClass();
}
}
Annotation-Driven Components
@Component
@RequestScope
public class OneClass {
...
}
@Component
@SessionScope
public class AnotherClass {
...
}
@Component
@ApplicationScope
public class YetAnotherClass {
...
}
@Component
@Scope(scopeName = WebApplicationContext.SCOPE_GLOBAL_SESSION, proxyMode =
ScopedProxyMode.TARGET_CLASS)
public class OneMoreClass {
...
}
@Component
@Scope(scopeName = "websocket", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class AndOneMoreClass {
...
}
In order to define a prototype-scoped bean, we need to add the @Scope annotation, specifying the type of scope
we want.
@Configuration
public class PrototypeConfiguration {
@Bean
@Scope("prototype")
public MyBean prototypeBean() {
return new MyBean("prototype");
}
}
In order to see how it works, we retrieve the bean from the Spring container and set a different value for its
property field. Next, we will again retrieve the bean from the container and look up its value:
Looking at the following result, we can see how a new instance has been created on each bean request:
A common mistake is to assume that the bean is recreated per invocation or per thread, this is NOT the case.
Instead an instance is created PER INJECTION (or retrieval from the context). If a Prototype scoped bean is only ever
injected into a single singleton bean, there will only ever be one instance of that Prototype scoped bean.
Spring does not manage the complete lifecycle of a prototype bean: the container instantiates, configures,
decorates and otherwise assembles a prototype object, hands it to the client and then has no further knowledge of
that prototype instance.
@Configuration
public class SingletonConfiguration {
@Bean
public MyBean singletonBean() {
return new MyBean("singleton");
}
}
The following example retrieves the same bean twice from the Spring context:
When logging the singletonBean2 property, the message "changed property" will be shown, since we just retrieved
the same shared instance.
Since the instance is shared among different components, it is recommended to define singleton scope for
stateless objects.
By default, singleton beans are pre-instantiated. Hence, the shared object instance will be created when the Spring
container is created. If we start the application, the "Initializing singleton bean..." message will be shown.
If we don't want the bean to be pre-instantiated, we can add the @Lazy annotation to the bean definition. This will
prevent the bean from being created until it is first requested.
Now, if we start the Spring container, no "Initializing lazy singleton bean..." message will appear. The bean won't be
created until it is requested for the first time:
If we run the application with both singleton and lazy singleton beans defined, It will produce the following
messages:
In Java config, use the above implementation as a condition to register the bean. Note the use of @Conditional
annotation.
@Configuration
public class MyAppConfig {
@Bean
@Conditional(PropertyCondition.class)
public MyBean myBean() {
return new MyBean();
}
}
In PropertyCondition, any number of conditions can be evaluated. However it is advised to separate the
implementation for each condition to keep them loosely coupled. For example:
@Configuration
public class MyAppConfig {
@Bean
@Conditional({PropertyCondition.class, SomeOtherCondition.class})
public MyBean myBean() {
return new MyBean();
}
}
Class conditions
Bean conditions
The @ConditionalOnBean and @ConditionalOnMissingBean annotations allow a bean to be included based on the
presence or absence of specific beans. You can use the value attribute to specify beans by type, or name to specify
beans by name. The search attribute allows you to limit the ApplicationContext hierarchy that should be
considered when searching for beans.
See the example above when we check whether there is no defined bean.
Property conditions
Resource conditions
The @ConditionalOnResource annotation allows configuration to be included only when a specific resource is
present.
@ConditionalOnResource(resources = "classpath:init-db.sql")
@Configuration
@ConditionalOnWebApplication
public class MyWebMvcAutoConfiguration {...}
The @ConditionalOnExpression annotation allows configuration to be included based on the result of a SpEL
expression.
@ConditionalOnExpression("${rest.security.enabled}==false")
@NotEmpty
@Size(min=5)
@Email
private String email;
}
Let's extend the User with a nested POJO Address we also need to validate.
@NotEmpty
@Size(min=2, max=3)
private String countryCode;
}
Just add @Valid annotation on address field to run validation of nested POJOs.
@NotEmpty
@Size(min=5)
@Email
private String email;
@Valid
private Address address;
}
@Min(18)
private int age;
//getters/setters
@RestController
public class ValidationController {
And a test.
@Test
public void testValid() throws Exception {
TestRestTemplate template = new TestRestTemplate();
String url = base + contextPath + "/validate";
Map<String, Object> params = new HashMap<>();
params.put("name", "");
params.put("age", "10");
assertThat(res, equalTo("ok"));
}
Both name and age are invalid so in the BindingResult we have two validation errors. Each has array of codes.
0 = "Min.userDTO.age"
1 = "Min.age"
2 = "Min.int"
3 = "Min"
0 = "NotEmpty.userDTO.name"
1 = "NotEmpty.name"
2 = "NotEmpty.java.lang.String"
3 = "NotEmpty"
@SpringBootApplication
@Configuration
public class DemoApplication {
@Bean(name = "messageSource")
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource bean = new ReloadableResourceBundleMessageSource();
bean.setBasename("classpath:custom");
@Bean(name = "validator")
public LocalValidatorFactoryBean validator() {
LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
bean.setValidationMessageSource(messageSource());
return bean;
}
The new value is shown for the error. To resolve message validator looks through the codes starting from the
beginning to find proper messages.
Thus when we define NotEmpty key in the .properties file for all cases where the @NotEmpty annotation is used our
message is applied.
If we define a message
All annotations where we app min check to integer values use the newly defined message.
The same logic could be applied if we need to localize the validation error messages.
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.2.0.Final</version>
</dependency>
Lets say the there is a rest api to create user in the system
@RequestMapping(value="/registeruser", method=RequestMethod.POST)
public String registerUser(User user);
User.java
@NotEmpty
@Size(min=5)
@Email
private String username;
@NotEmpty
private String password;
@NotEmpty
private String password2;
We may also need to have a business validator like password and password2(confirm password) are same, for this
we can add a custom validator as below. Write a custom annotation for annotating the data field.
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PasswordValidator.class)
public @interface GoodPassword {
String message() default "Passwords won't match.";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
@Override
public boolean isValid(User user, ConstraintValidatorContext context) {
return user.getPassword().equals(user.getPassword2());
}
}
@GoodPassword
public class User {
@NotEmpty
@Size(min=5)
@Email
@NotEmpty
private String password;
@NotEmpty
private String password2;
}
@Valid triggers validation in Spring. BindingResult is an object injected by spring which has list of errors after
validation.
JSR 303 annotation has message attributes on them which can be used for providing custom messages.
@GoodPassword
public class User {
The configuration class needs only to be a class that is on the classpath of your application and visible to your
applications main class.
class MyApp {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext appContext =
new AnnotationConfigApplicationContext(MyConfig.class);
@Configuration
class MyConfig {
@Bean
MyObject myObject() {
// ...configure myObject...
}
Xml Config
The configuration xml file needs only be on the classpath of your application.
class MyApp {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext appContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
Autowiring
Autowiring needs to know which base packages to scan for annotated beans (@Component). This is specified via the
#scan(String...) method.
class MyApp {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext appContext =
new AnnotationConfigApplicationContext();
appContext.scan("com.example");
appContext.refresh();
/**
* An Author created with the constructor that initializes the
* name fields
*/
@Bean
Author author2() {
return new Author("Steven", "King");
}
/**
* An Author created with the default constructor, but
* then uses the property setters to specify name fields
*/
@Bean
Author author3() {
Author author = new Author();
author.setFirstName("George");
author.setLastName("Martin");
return author;
}
/**
* A Book created referring to author2 (created above) via
* a constructor argument. The dependency is fulfilled by
* invoking the method as plain Java.
*/
@Bean
Book book1() {
return new Book(author2(), "It");
}
/**
* A Book created referring to author3 (created above) via
* a property setter. The dependency is fulfilled by
* invoking the method as plain Java.
*/
@Bean
Book book2() {
Book book = new Book();
book.setAuthor(author3());
book.setTitle("A Game of Thrones");
return book;
}
}
Note that you cannot simply return the InputStream from the extractor, because by the time the execute method
returns, the underlying connection and stream are already closed.
Also you can add an interceptor to your RestTemplate if you need to add the same headers to multiple requests:
As described in the Spring documentation, Apache HttpClient may be used as the underlying implementation to
create HTTP requests by using the HttpComponentsClientHttpRequestFactory. HttpClient can be configured to do
preemptive basic authentication.
/**
* {@link HttpComponentsClientHttpRequestFactory} with preemptive basic
* authentication to avoid the unnecessary first 401 response asking for
* credentials.
* <p>
* Only preemptively sends the given credentials to the given host and
* optionally to its subdomains. Matching subdomains can be useful for APIs
* using multiple subdomains which are not always known in advance.
* <p>
* Other configurations of the {@link HttpClient} are not modified (e.g. the
* default credentials provider).
*/
public class PreAuthHttpComponentsClientHttpRequestFactory extends
HttpComponentsClientHttpRequestFactory {
/**
@Override
protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) {
// Add AuthCache to the execution context
HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(new PreAuthCredentialsProvider());
context.setAuthCache(new PreAuthAuthCache());
return context;
}
/**
* @param host
* host name
* @return whether the configured credentials should be used for the given
* host
*/
protected boolean hostNameMatches(String host) {
return host.equals(hostName) || (matchSubDomains && host.endsWith("." + hostName));
}
@Configuration
@EnableScheduling
public class MyConfig {
Notes: -
Example: -
syntax means
------------------------------------------------------------------------------------
"0 0 * * * *" the top of every hour of every day.
"*/10 * * * * *" every ten seconds.
"0 0 8-10 * * *" 8, 9 and 10 o'clock of every day.
"0 0/30 8-10 * * *" 8:00, 8:30, 9:00, 9:30 and 10 o'clock every day.
"0 0 9-17 * * MON-FRI" on the hour nine-to-five weekdays
"0 0 0 25 12 ?" every Christmas Day at midnight
A method declared with @Scheduled() is called explicitly for every matching case.
If we want some code to be executed when a cron expression is met, then we have to specify it in the annotation:
@Component
public class MyScheduler{
If we want to print current time in our console for every after 5 seconds -
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
@Component
public class Scheduler {
Example class:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
@Component("schedulerBean")
public class Scheduler {
Example XML(task-context.xml):
<task:scheduled-tasks scheduler="scheduledTasks">
<task:scheduled ref="schedulerBean" method="currentTime" cron="*/5 * * * * MON-FRI" />
</task:scheduled-tasks>
</beans>
@Component
public class MyScheduler{
@Scheduled(fixedDelay=5000)
public void doSomething() {
// this will execute periodically, after the one before finishes
}
}
@Component
public class MyScheduler{
@Scheduled(fixedRate=5000)
public void doSomething() {
// this will execute periodically
}
}
lazy-init in spring is the attribute of bean tag. The values of lazy-init are true and false. If lazy-init is true, then that
bean will be initialized when a request is made to bean. This bean will not be initialized when the spring container is
initialized. If lazy-init is false then the bean will be initialized with the spring container initialization and this is the
default behavior.
app-conf.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd">
A.java
package com.concretepage;
public class A {
public A(){
System.out.println("Bean A is initialized");
}
}
B.java
package com.concretepage;
public class B {
public B(){
System.out.println("Bean B is initialized");
}
}
SpringTest.java
package com.concretepage;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("app-conf.xml");
System.out.println("Feth bean B.");
context.getBean("testB");
}
}
Bean A is initialized
Feth bean B.
Bean B is initialized
@Component
public class B {
@Autowired
@Lazy // If this is not here, Demo will still get eagerly instantiated to satisfy this request.
private Demo demo;
.......
}
@Bean
@Lazy
public Demo demo() {
return new Demo();
}
}
nexus.user=admin
nexus.pass=admin
nexus.rest.uri=http://xxx.xxx.xxx.xxx:xxxx/nexus/service/local/artifact/maven/content
@Component
@PropertySource(value = { "classpath:nexus.properties" })
public class NexusBean {
@Configuration
class AppConfig {
@Bean
public Bar bar() { return new Bar(); }
@Bean
public Foo foo(Bar bar) { return new Foo(bar); }
}
<context:annotation-config/>
<context:component-scan base-package="[base package]"/>
where, base-package is the fully-qualified Java package within which Spring should perform component scan.
Constructor injection
@Component
class Bar { ... }
@Component
class Foo {
private Bar bar;
@Autowired
public Foo(Bar bar) { this.bar = bar; }
}
Here, @Autowired is a Spring-specific annotation. Spring also supports JSR-299 to enable application portability to
other Java-based dependency injection frameworks. This allows @Autowired to be replaced with @Inject as:
@Component
class Foo {
private Bar bar;
@Inject
public Foo(Bar bar) { this.bar = bar; }
}
@Component
class Foo {
private Bar bar;
@Autowired
public void setBar(Bar bar) { this.bar = bar; }
}
Field injection
Autowiring also allows initializing fields within class instances directly, as follows:
@Component
class Foo {
@Autowired
private Bar bar;
}
For Spring versions 4.1+ you can use Optional for optional dependencies.
@Component
class Foo {
@Autowired
private Optional<Bar> bar;
}
@Component
class Foo {
private Optional<Bar> bar;
@Autowired
Foo(Optional<Bar> bar) {
this.bar = bar;
}
}
class Foo {
private Bar bar;
Constructor injection
When using XML configuration for Spring framework to define Spring-managed beans, a bean of type Foo can be
configured as follows:
<bean class="Foo">
<constructor-arg>
<bean class="Bar" />
</constructor-arg>
</bean>
<bean class="Foo">
<constructor-arg ref="bar" />
</bean>
In both cases, Spring framework first creates an instance of Bar and injects it into an instance of Foo. This example
assumes that the class Foo has a constructor that can take a Bar instance as a parameter, that is:
class Foo {
private Bar bar;
This style is known as constructor injection because the dependency (Bar instance) is being injected into through
the class constructor.
Property injection
<bean class="Foo">
<property name="bar">
<bean class="Bar" />
</property>
</bean>
<bean class="Foo">
<property name="bar" ref="bar" />
</bean>
This requires the Foo class to have a setter method that accepts a Bar instance, such as:
Constructor injection
@Configuration
class AppConfig {
@Bean
public Bar bar() { return new Bar(); }
@Bean
public Foo foo() { return new Foo(bar()); }
}
Property injection
@Configuration
class AppConfig {
@Bean
public Bar bar() { return new Bar(); }
@Bean
public Foo foo() {
Foo foo = new Foo();
foo.setBar(bar());
return foo;
}
}
Instances of the JdbcTemplate class are threadsafe once configured so it can be safely inject this shared reference
into multiple DAOs.
OR
while(rowSet.next())
{
String firstName = rowSet.getString("first_name");
String lastName = rowSet.getString("last_name");
System.out.println("Vorname: " + firstName);
System.out.println("Nachname: " + lastName);
System.out.println("---”);
}
OR
@Override
public Customer mapRow(ResultSet rs, int rowNum) throws SQLException
{
Customer customer = new Customer();
customer.setFirstName(rs.getString("first_Name"));
customer.setLastName(rs.getString("first_Name"));
customer.setEmail(rs.getString("email"));
return customer;
}
});
Batch Insert
@Override
public int getBatchSize() {
return l.size();
}
Batch Update
@Override
public int getBatchSize() {
return l.size();
}
});
There are further batchUpdate methods which accept List of object array as input parameters. These methods
internally use BatchPreparedStatementSetter to set the values from the list of arrays into sql statement.
The NamedParameterJdbcTemplate class adds support for programming JDBC statements using named
parameters, as opposed to programming JDBC statements using only classic placeholder ( '?') arguments.
The NamedParameterJdbcTemplate class wraps a JdbcTemplate, and delegates to the wrapped
JdbcTemplate to do much of its work.
import java.io.IOException;
import java.net.HttpURLConnection;
import org.springframework.ws.transport.http.HttpUrlConnectionMessageSender;
import sun.misc.BASE64Encoder;
@Override
protected void prepareConnection(HttpURLConnection connection)
throws IOException {
super.prepareConnection(connection);
}
}
myWSClient.setMessageSender(new CustomWSMessageSender());
@Configuration
@Profile("production")
public class ProductionConfiguration {
// ...
}
<beans profile="dev">
<bean id="dataSource" class="<some data source class>" />
</beans>
spring.profiles.active=dev,production
--spring.profiles.active=dev,hsqldb
or in SpringBoot
SpringApplication.setAdditionalProfiles("dev");
The context:component-scan element defines the base-package where DispatcherServlet will search the controller
class.
The prefix+string returned by controller+suffix page will be invoked for the view component.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
</beans>
AdamIJK Chapter 12
Arlo Chapter 4
bernie Chapter 10
Bond Chapter 7
CollinD Chapter 5
Constantine Chapters 5 and 6
DavidR Chapter 12
dimitrisli Chapter 1
eltabo Chapter 10
Gautam Jose Chapter 13
guille11 Chapters 11 and 16
Harshal Patil Chapter 5
Hitesh Kumar Chapter 1
ipsi Chapter 1
JamesENL Chapter 5
Johir Chapter 11
manish Chapter 14
Moshe Arad Chapter 12
mszymborski Chapter 5
nicholas.hauschild Chapter 9
Panther Chapters 1, 6 and 13
Praneeth Ramesh Chapter 8
Rajanikanta Pradhan Chapters 1 and 2
Sergii Bishyr Chapter 14
Setu Chapter 15
smichel Chapter 15
Srinivas Gadilli Chapter 18
StanislavL Chapters 5, 7, 8, 10, 15 and 17
Stefan Isele Chapter 5
Taylor Chapter 6
Tim Tong Chapters 5 and 6
walsh Chapter 3
xpadro Chapter 6
Xtreme Biker Chapter 11