Skip to main content
Wiring the different layers
Ilio Catallo - info@iliocatallo.it
Outline
• Adding a back-end container
• Wiring the different layers
• References
Adding a back-end container
Web beans
DispatcherServlet ini$alizes its DI container from a single file
named frontcontroller-servlet.xml
+---------------------------------------------------+
| |
| |
| |
| +------------+ +------------+ |
| | +------------+ | +------------+ |
| | | +-------------+ | | +-------------+ |
| | | | | | | | | |
| +-+ | Controllers | +-+ | Special | |
| +-+ | +-+ beans | |
| +-------------+ +-------------+ |
| |
| |
| |
+---------------------------------------------------+
Spring DI Container
Web beans
Controllers and special beans are the Web-specific components
(Web beans) of our applica9on
+---------------------------------------------------+
| |
| |
| |
| +------------+ +------------+ |
| | +------------+ | +------------+ |
| | | +-------------+ | | +-------------+ |
| | | | | | | | | |
| +-+ | Controllers | +-+ | Special | |
| +-+ | +-+ beans | |
| +-------------+ +-------------+ |
| |
| |
| |
+---------------------------------------------------+
Spring DI Container
Service and persistence beans
What about all the other applica,on components (beans) that we
will need for our applica6on?
+---------------------------------------------------+ +--------------+
| | | +--------------+
| | | | +---------------+
| | | | | |
| +------------+ +------------+ | +-+ | Service beans |
| | +------------+ | +------------+ | +-+ |
| | | +-------------+ | | +-------------+ | +---------------+
| | | | | | | | | |
| +-+ | Controllers | +-+ | Special | | +--------------+
| +-+ | +-+ beans | | | +--------------+
| +-------------+ +-------------+ | | | +---------------+
| | | | | |
| | | | | Persistence |
| | +-+ | beans |
+---------------------------------------------------+ +-| |
Spring DI Container +---------------+
Service and persistence beans
Do we have also to declare service and persistence beans into
frontcontroller-servlet.xml?
+---------------------------------------------------+ +--------------+
| | | +--------------+
| | | | +---------------+
| | | | | |
| +------------+ +------------+ | +-+ | Service beans |
| | +------------+ | +------------+ | +-+ |
| | | +-------------+ | | +-------------+ | +---------------+
| | | | | | | | | |
| +-+ | Controllers | +-+ | Special | | +--------------+
| +-+ | +-+ beans | | | +--------------+
| +-------------+ +-------------+ | | | +---------------+
| | | | | |
| | | | | Persistence |
| | +-+ | beans |
+---------------------------------------------------+ +-| |
Spring DI Container +---------------+
Mul$ple configura$on files
Although not strictly required, it is a good idea to organize our
Spring configura8on across mul+ple files
Mul$ple configura$on files
We will add some addi,onal XML configura,on files
• One for the service layer
• One for the persistence layer
• One for data source configura7on
Spli%ng by architectural layers
By doing so, we separate applica&on beans (services and
persistence beans) from Web beans (controllers and special beans)
Spli%ng by architectural layers
That is, the Spring configura3on is broken out by architectural
layers
┌──────┐┌────────────────────────────────┐
│ D ││ │
│ o ││ Presentation layer │
│ m ││ │
│ a │└────────────────────────────────┘
│ i │┌────────────────────────────────┐
│ n ││ │
│ ││ Service layer │
│ m ││ │
│ o │└────────────────────────────────┘
│ d │┌────────────────────────────────┐
│ e ││ │
│ l ││ Persistence layer │
│ ││ │
└──────┘└────────────────────────────────┘
ContextLoaderListener
ContextLoaderListener is a Spring's component capable of
loading addi$onal configura6on files
Event listeners
The Java Servlet specifica1on includes the capability to track
events in a Web applica1on through event listeners
ServletContextListener
We can monitor events related to the Web app lifecycle by means
of a ServletContextListener implementa5on
public interface ServletContextListener {
public void contextInitialized(ServletContextEvent sce);
public void contextDestroyed(ServletContextEvent sce);
}
ServletContextListener
ServletContextListeners are loaded at Web container
startup, before any servlet
public interface ServletContextListener {
public void contextInitialized(ServletContextEvent sce);
public void contextDestroyed(ServletContextEvent sce);
}
ContextLoaderListener
ContextLoaderListener implements the
ServletContextListener interface
public class ContextLoaderListener implements ServletContextListener { ... }
ContextLoaderListener
As with any Web component, we need to declare
ContextLoaderListener in web.xml
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
ContextLoaderListener
The loca)ons of the addi)onal configura)on files are specified as a
context parameter named contextConfigLocation1
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:service-context.xml
classpath:persistence-context.xml
classpath:dataSource-context.xml
</param-value>
</context-param>
1
Note that we are not allowed to specify any other parameter name
ContextLoaderListener
The classpath: prefix is used to inform Spring that the files are
located in the CLASSPATH
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:service-context.xml
classpath:persistence-context.xml
classpath:dataSource-context.xml
</param-value>
</context-param>
One configura,on file per layer
Service beans are declared in service-context.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:service-context.xml <!-- Service beans -->
classpath:persistence-context.xml
classpath:dataSource-context.xml
</param-value>
</context-param>
One configura,on file per layer
Persistence beans are declared in persistence-context.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:service-context.xml
classpath:persistence-context.xml <!-- Persistence beans -->
classpath:dataSource-context.xml
</param-value>
</context-param>
One configura,on file per layer
Finally, dataSource-context.xml configures the data source
we would like to use
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:service-context.xml
classpath:persistence-context.xml
classpath:dataSource-context.xml <!-- data source config -->
</param-value>
</context-param>
How do the addi+onal configura+on files relate to
frontcontroller-servlet.xml?
Back-end container
The ContextLoaderListener bootstraps an addi$onal
container called the back-end container
+--------------------------------------+
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
+--------------------------------------+
Spring DI back-end container
Separa&ng the different areas
Service and persistence beans will live within the back-end
container...
+---------------------------------------------------+
| |
| |
| +--------------+ |
| | +--------------+ +--------------+ |
| | | +--------------- | +--------------+ |
| | | | + | | +---------------+ |
| +-+ | Service beans | | | | | |
| +-+ | | | | Persistence | |
| +---------------| +-+ | beans | |
| +-+ | |
| +---------------+ |
| |
| |
+---------------------------------------------------+
Spring DI back-end container
Separa&ng the different areas
...whereas Web beans will live in the front-end container created
by DispatcherServlet
+---------------------------------------------------+
| |
| |
| |
| +------------+ +------------+ |
| | +------------+ | +------------+ |
| | | +-------------+ | | +-------------+ |
| | | | | | | | | |
| +-+ | Controllers | +-+ | Special | |
| +-+ | +-+ beans | |
| +-------------+ +-------------+ |
| |
| |
| |
+---------------------------------------------------+
Spring DI front-end container
Separa&ng the different areas
We are effec(vely separa&ng the applica(on beans from the Web
beans by crea(ng different containers
+-------------------------+ +-------------------------+
| | | |
| | | |
| <----> |
| | | |
| | | |
+-------------------------+ +-------------------------+
Front-end container Back-end container
The back-end container is unique
Remember: the back-end container is unique
+---------------------------------------------------+
| |
| |
| +--------------+ |
| | +--------------+ +--------------+ |
| | | +--------------- | +--------------+ |
| | | | + | | +---------------+ |
| +-+ | Service beans | | | | | |
| +-+ | | | | Persistence | |
| +---------------| +-+ | beans | |
| +-+ | |
| +---------------+ |
| |
| |
+---------------------------------------------------+
Spring DI back-end container
The back-end container is unique
In other words, ContextLoaderListener loads the different
configura5on files into the same back-end container
+---------------------------------------------------+
| |
| |
| +--------------+ |
| | +--------------+ +--------------+ |
| | | +--------------- | +--------------+ |
| | | | + | | +---------------+ |
| +-+ | Service beans | | | | | |
| +-+ | | | | Persistence | |
| +---------------| +-+ | beans | |
| +-+ | |
| +---------------+ |
| |
| |
+---------------------------------------------------+
Spring DI back-end container
Parent-child rela.onship
The back-end container serves as a parent for the front-end
container
+----------------------+
| |
| Back-end container |
| |
+----------^-----------+
|
| Child of...
|
+----------+-----------+
| |
| Front-end container |
| |
+----------------------+
Parent-child rela.onship
That is why the back-end container is also called the root container
+----------------------+
| |
| Back-end container |
| |
+----------^-----------+
|
| Child of...
|
+----------+-----------+
| |
| Front-end container |
| |
+----------------------+
Parent-child rela.onship
A container can only have a single parent, but it can have mul6ple
children
+--------------+
| |
| Container A |
| |
+------^-------+
|
+--------------+-------------+
| |
+------+-------+ +-------+------+
| | | |
| Container B | | Container C |
| | | |
+--------------+ +------^-------+
|
+--------------+-------------+
| |
+------+-------+ +-------+------+
| | | |
| Container D | | Container E |
| | | |
+--------------+ +--------------+
Parent-child rela.onship
Child containers can access beans defined in the parent container
+--------------+
| |
| Container A |
| |
+------^-------+
|
+--------------+-------------+
| |
+------+-------+ +-------+------+
| | | |
| Container B | | Container C |
| | | |
+--------------+ +------^-------+
|
+--------------+-------------+
| |
+------+-------+ +-------+------+
| | | |
| Container D | | Container E |
| | | |
+--------------+ +--------------+
Parent-child rela.onship
However, parent beans cannot access beans in the child container
+--------------+
| |
| Container A |
| |
+------^-------+
|
+--------------+-------------+
| |
+------+-------+ +-------+------+
| | | |
| Container B | | Container C |
| | | |
+--------------+ +------^-------+
|
+--------------+-------------+
| |
+------+-------+ +-------+------+
| | | |
| Container D | | Container E |
| | | |
+--------------+ +--------------+
Parent-child rela.onship
Hence, shared beans and infrastructure configura2on are
• Declared in the back-end container
• Consumed in the front-end container by Web components
Wiring the different layers
Discovering beans
Once created, we have to declare which beans are going to be part
of the back-end container
+---------------------------------------------------+
| |
| |
| +--------------+ |
| | +--------------+ +--------------+ |
| | | +--------------- | +--------------+ |
| | | | + | | +---------------+ |
| +-+ | Service beans | | | | | |
| +-+ | | | | Persistence | |
| +---------------| +-+ | beans | |
| +-+ | |
| +---------------+ |
| |
| |
+---------------------------------------------------+
Spring DI back-end container
Discovering beans
We can configure Spring to automa&cally discover beans and
declare them in the back-end container
Stereotype annota+ons
To this end, four stereotype annota+ons are available
• @Component
• @Controller
• @Service
• @Repository
Stereotype annota+ons
Both @Controller, @Service and @Repository are
specializa2on of @Component
Service beans
Service beans should be annotated with the @Service annota/on
@Service
public class AccountServiceImpl implements AccountService { ... }
Service beans
Currently, @Service does not provide any addi1onal behavior
over the @Component annota1on
@Service
public class AccountServiceImpl implements AccountService { ... }
Service beans
However, this annota/on might include service layer specific
func/onality in future Spring releases
@Service
public class AccountServiceImpl implements AccountService { ... }
Service beans
Nevertheless, @Service is s,ll useful, as it helps in clearly
demarca-ng the role of the bean
@Service
public class AccountServiceImpl implements AccountService { ... }
Persistence beans
Persistence beans should be annotated with the @Repository
annota/on
@Repository
public class AccountRepositoryImpl implements AccountRepository { ... }
Persistence beans
Like @Service, the @Repository is a specializa/on of the
@Component annota/on
Persistence beans
The @Repository annota)on makes the unchecked excep+ons
thrown by the repository bean eligible for transla)on into Spring's
DataAccessExceptions
Auto-discovering beans
With all the @Service and @Repository annota,ons in place,
we are now ready to auto-discover beans
Auto-discovering beans
The auto-discovery mechanism will find all the service and
persistence beans without having to provide XML configura<on
entries for them
Auto-discovering beans
The <context:component-scan> loads into the container
those beans annotated with any @Component specializa4on
Auto-discovering beans
service-context.xml:
<beans>
<context:component-scan
base-package="it.polimi.awt.springmvc.service"/>
</beans>
Auto-discovering beans
persistence-context.xml:
<beans>
<context:component-scan
base-package="it.polimi.awt.springmvc.repository"/>
</beans>
Auto-discovering beans
No#ce that we already used the auto-discovery mechanism, since
@Controller is also a @Component specializa#on
Auto-discovering beans
frontcontroller-servlet.xml:
<context:component-scan
base-package="it.polimi.awt.springmvc.web"/>
Beans injec*on
With the back-end container in place, we are now ready to inject
instances of the service beans into the controllers
Annota&on-based wiring
The most common way of wiring beans is to use annota%ons
@Controller
@RequestMapping("/account")
public class AccountController {
private AccountService accountService;
@PleaseInjectHere
public AccountController(AccountService accountService) {
accountService = accountService;
}
}
Annota&on-based wiring
It turns out that Spring supports different annota+ons
• The @Autowired annota*on (Spring API)
• The @Inject annota*on (Dependency Injec*on API)
• The @Resource annota*on (Common Annota*ons API)
Annota&on-based wiring
It turns out that Spring supports different annota+ons
• The @Autowired annota)on (Spring API)
• The @Inject annota*on (Dependency Injec*on API)
• The @Resource annota*on (Common Annota*ons API)
@Autowired
When Spring sees something annotated with @Autowired, it will
try to perform wiring by type
@Autowired
@Autowired can be used:
• On fields
• On se*er methods
• On constructor methods
• On methods with arbitrary signature
@Autowired
@Controller
@RequestMapping("/account")
public class AccountController {
private AccountService accountService;
@Autowired
public AccountController(AccountService accountService) {
accountService = accountService;
}
}
Resolving dependencies
If no bean can be wired into the @Autowired-annotated
argument, a NoSuchBeanDefinitionException will be thrown
Resolving dependencies
If more than one bean are suitable for injec1on, @Autowired
cannot determine which one to choose...
Resolving dependencies
...and so a NoSuchBeanDefinitionException will be thrown
Annota&on-based wiring
It turns out that Spring supports different annota2ons:
• The @Autowired annota*on (Spring API)
• The @Inject annota)on (Dependency Injec)on API)
• The @Resource annota*on (Common Annota*ons API)
Dependency Injec+on API
Spring 3 added support for annota1ons coming from the
Dependency Injec+on API (JSR-330)
Dependency Injec+on API
JSR-330 defines some annota1ons contained in the
javax.inject package, such as @Inject and @Named
@Inject
The centerpiece of JSR-330 is the @Inject annota5on. This
annota5on is an almost complete drop-in replacement for Spring’s
@Autowired annota5on
@Inject
@Controller
@RequestMapping("/account")
public class AccountController {
private AccountService accountService;
@Inject
public AccountController(AccountService accountService) {
accountService = accountService;
}
}
Wiring the persistence layer
Of course, we can use @Autowired also to inject persistence
beans into service beans
Wiring the persistence layer
@Service
public class AccountServiceImpl implements AccountService {
private AccountRepository accountRepository;
@Autowired
public AccountServiceImpl(AccountRepository accountRepository) {
this.accountRepository = accountRepository;
}
}
References
References
• SpringSource, Spring Framework Reference
• SpringSource, ContextLoader Java-doc
• M. Deinum, K. Serneels, Pro Spring MVC: with Web flows,
Apress PublicaIons
• Craig Walls, Spring in AcIon (3rd EdiIon),
Manning PublicaIons
• Willie Wheeler, Spring in PracIce, Manning PublicaIons