SlideShare a Scribd company logo
1 of 54
Download to read offline
Spring framework
Motto: Musíte rozbít vejce když chcete udělat omeletu
Spring framework training materials by Roman Pichlík is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Tuesday 28 May 13
IoC container
Advanced
Tuesday 28 May 13
Agenda
• Hierarchická konfigurace
• Dynamické nahrávání kontextů
• PropertyEditory
• Validace
• SPEL
Tuesday 28 May 13
Konfigurace na druhou
Tuesday 28 May 13
Properties
Tuesday 28 May 13
Property placeholders
• Konfigurace mimo XML
• Atributy spjaté s prostředím
• databáze, HTTP endpointy atd.
• známe až v deploy time
Tuesday 28 May 13
- Operations opravdu neradi editují XML v zanorenem JARu na filesystemu
Příklad
@Component
public class MyAnnotatedBean {
	 @Value("${username}")
	 private String username;
	 public String getUsername() {
	 	 return username;
	 }
}
Tuesday 28 May 13
Složitější případ užití
• Proč jeden soubor nestačí
• různá prostředí
• testy, produkce, developer stroj
• chceme definovat smart defaults
Tuesday 28 May 13
Konfigurační hierarchie
• Každá komponenta může
definovat default hodnoty
• Aplikace definuje svoje
default hodnoty
• Prostředí definuje svoje
hodnoty
Component defaults
Application defaults
Environment values
přepisuje
Tuesday 28 May 13
System.properties override
Provedení
• Pořadí definice určuje prioritu
• Dynamické načítání z
classpath
• Chybějící properties soubory
se ignorují
• přenositelnost
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="true" />
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="locations">
<list>
<value>classpath*:META-INF/componentDefault.properties</value>
<value>classpath:META-INF/applicationDefault.properties</value>
<value>file:/opt/configuration/deployment.properties</value>
</list>
</property>
</bean>
Tuesday 28 May 13
Resource abstrakce
Tuesday 28 May 13
Resource
• Spring abstrakce pro přístup k
souborům v různém prostředí
Prefix Příklad Vysvětlivka
classpath: classpath:com/myapp/config.xml Nahravá se z classpath
file: file:/data/config.xml Nahrává se z FS
http: http://myserver/logo.png Nahrává přes URL
Bez prefixu /data/config.xml Závisí na typu ApplicationContext
Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt");
<bean id="myBean" class="...">
<property name="template" value="some/resource/path/myTemplate.txt"/>
</bean>
Tuesday 28 May 13
Wildcards & Ant path
/WEB-INF/*-context.xml
classpath:com/mycompany/**/applicationContext.xml
classpath*:META-INF/*-beans.xml
• Wildcard *
• nahrání více resourců
• komplexní boot aplikace
Tuesday 28 May 13
Dynamické sestavení kontextu
Tuesday 28 May 13
Motivace
• Pouze ze začátku vystačí jeden
bean definition file na aplikace
• nepraktické
• chceme oddělit definici bean
podle komponenty nebo typu
• přehlednost
Tuesday 28 May 13
Využití Resource abstrakce
• Definujte kontexty v předem
definované cestě
• META-INF/company/spring
• Pojmenované s pevným suffixem
• *-applicationContext.xml
Tuesday 28 May 13
Inicializace
• Automatické načtení všech
bean definic na classpath
• usnadňuje přidávání
nových kontextů
• umožňuje dynamické
načítání podle toho jak je
classpath sestavena
• někdy méně přehledné
String path =
"classpath*:META-INF/company/*-applicationContext.xml";
new ClassPathXmlApplicationContext(path);
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:META-INF/company/*-applicationContext.xml
</param-value>
</context-param>
Tuesday 28 May 13
Strategický context
• Definuje infrastrukturní beany
používané v celé aplikaci
• DataSource, Transakční manažer,
HibernateSessionFactory atd.
• Může mít různou podobu pro
různá prostředí
• Testy, Produkce, Aplikační server
Tuesday 28 May 13
- nejdulezitejsi beany na jednom miste
- lze pouzit import
PropertyEditors
Tuesday 28 May 13
java.beans.PropertyEditor
• Rozhraní pro konverzi String –>
Datový typ ve Springu
• Používá se
• inicializace kontejneru a
nastavování bean values
• Spring MVC konverze z query
params (?name=dagi&age=31)
Tuesday 28 May 13
public class BeanWithSpecialDate {
private SpecialDateType specialDateType;
public SpecialDateType getSpecialDateType() {
return specialDateType;
}
public void setSpecialDateType(SpecialDateType specialDateType) {
this.specialDateType = specialDateType;
}
}
public class SpecialDateType {
private final Date date;
public SpecialDateType(Date date) {
this.date = date;
}
public Date getDate() {
return date;
}
}
public class SpecialDatePropertyEditor extends PropertyEditorSupport{
@Override
public void setAsText(String text) throws IllegalArgumentException {
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
try {
setValue(new SpecialDateType(sdf.parse(text)));
} catch (ParseException e) {
throw new IllegalArgumentException("Cannot parse date", e);
}
}
}
<bean class="cz.sweb.pichlik.springioc.propertyeditor.BeanWithSpecialDate">
<property name="specialDateType" value="01-01-2000" />
</bean>
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry
key="cz.sweb.pichlik.springioc.propertyeditor.SpecialDateType"
value="cz.sweb.pichlik.springioc.propertyeditor.SpecialDatePropertyEditor"/>
</map>
</property>
</bean>
je definovaná
sespeciálním
typem
uvedeným jako String
Tuesday 28 May 13
public class BeanWithSpecialDate {
private SpecialDateType specialDateType;
public SpecialDateType getSpecialDateType() {
return specialDateType;
}
public void setSpecialDateType(SpecialDateType specialDateType) {
this.specialDateType = specialDateType;
}
}
public class SpecialDateType {
private final Date date;
public SpecialDateType(Date date) {
this.date = date;
}
public Date getDate() {
return date;
}
}
public class SpecialDatePropertyEditor extends PropertyEditorSupport{
@Override
public void setAsText(String text) throws IllegalArgumentException {
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
try {
setValue(new SpecialDateType(sdf.parse(text)));
} catch (ParseException e) {
throw new IllegalArgumentException("Cannot parse date", e);
}
}
}
<bean class="cz.sweb.pichlik.springioc.propertyeditor.BeanWithSpecialDate">
<property name="specialDateType" value="01-01-2000" />
</bean>
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry
key="cz.sweb.pichlik.springioc.propertyeditor.SpecialDateType"
value="cz.sweb.pichlik.springioc.propertyeditor.SpecialDatePropertyEditor"/>
</map>
</property>
</bean>
o jehož konverzi se stará PropertyEditor
Tuesday 28 May 13
public class BeanWithSpecialDate {
private SpecialDateType specialDateType;
public SpecialDateType getSpecialDateType() {
return specialDateType;
}
public void setSpecialDateType(SpecialDateType specialDateType) {
this.specialDateType = specialDateType;
}
}
public class SpecialDateType {
private final Date date;
public SpecialDateType(Date date) {
this.date = date;
}
public Date getDate() {
return date;
}
}
public class SpecialDatePropertyEditor extends PropertyEditorSupport{
@Override
public void setAsText(String text) throws IllegalArgumentException {
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
try {
setValue(new SpecialDateType(sdf.parse(text)));
} catch (ParseException e) {
throw new IllegalArgumentException("Cannot parse date", e);
}
}
}
<bean class="cz.sweb.pichlik.springioc.propertyeditor.BeanWithSpecialDate">
<property name="specialDateType" value="01-01-2000" />
</bean>
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry
key="cz.sweb.pichlik.springioc.propertyeditor.SpecialDateType"
value="cz.sweb.pichlik.springioc.propertyeditor.SpecialDatePropertyEditor"/>
</map>
</property>
</bean>
patřičně zaregistrovaný
Tuesday 28 May 13
public class BeanWithSpecialDate {
private SpecialDateType specialDateType;
public SpecialDateType getSpecialDateType() {
return specialDateType;
}
public void setSpecialDateType(SpecialDateType specialDateType) {
this.specialDateType = specialDateType;
}
}
public class SpecialDateType {
private final Date date;
public SpecialDateType(Date date) {
this.date = date;
}
public Date getDate() {
return date;
}
}
public class SpecialDatePropertyEditor extends PropertyEditorSupport{
@Override
public void setAsText(String text) throws IllegalArgumentException {
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
try {
setValue(new SpecialDateType(sdf.parse(text)));
} catch (ParseException e) {
throw new IllegalArgumentException("Cannot parse date", e);
}
}
}
<bean class="cz.sweb.pichlik.springioc.propertyeditor.BeanWithSpecialDate">
<property name="specialDateType" value="01-01-2000" />
</bean>
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry
key="cz.sweb.pichlik.springioc.propertyeditor.SpecialDateType"
value="cz.sweb.pichlik.springioc.propertyeditor.SpecialDatePropertyEditor"/>
</map>
</property>
</bean>
je definovaná
sespeciálním
typem
uvedeným jako String
o jehož konverzi se stará PropertyEditor
patřičně zaregistrovaný
Tuesday 28 May 13
Validate
Tuesday 28 May 13
• Řešeno přes Bean Validation
• JSR 303
• Možnost použití přes různé int.
• org.springframework.validation
• javax.validation.Validator
• Integrace do Spring MVC
Tuesday 28 May 13
@Service
public class MyService {
@Autowired
private Validator validator;
public void doSomethingWithPerson(Person person){
Set<ConstraintViolation<Person>> resultOfValidation = validator.validate(person);
for (ConstraintViolation<Person> constraintViolation : resultOfValidation) {
throw new IllegalArgumentException(constraintViolation.getMessage());
}
}
}
public class Person {
	 @DecimalMax(value="110", message="Maximum age is 110")
	 @DecimalMin(value="0", message="Minimum age is 0")
	 private int age;
	 @NotNull
	 @Valid
	 private Address address;
	 public Person() {
	 	 super();
	 }
	 public Person(int age, Address address) {
	 	 super();
	 	 this.age = age;
	 	 this.address = address;
	 }
}
<bean class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
používávalidátor
validuje
JSR 303 validační anotace
Tuesday 28 May 13
SPEL
Tuesday 28 May 13
Spring EL
• Expression Language
• operátory, volání metod,
proměnné a mnohem víc
• přímé použití jako EL
• definice bean
Tuesday 28 May 13
Použití
• Jako EL ve vlastní aplikaci
• V rámcí definice bean
• Lze použít i v anotaci
@Value
ExpressionParser p = new SpelExpressionParser();
Expression exp =
p.parseExpression("'Hello World'.concat('!')");
String message = (String) exp.getValue();
<bean id="numberGuess" class="org.spring.samples.NumberGuess">
<property name="randomNumber" value="#{ T(java.lang.Math).random() * 100.0 }"/>
</bean>
Tuesday 28 May 13
používání v definici bean vede k programování na úrovni XML => Ant syndrom
Vhodné použití
• Enums, Constanty v XML
<bean class="cz.sweb.pichlik.springioc.spel.ColorBean">
<property name="color" value="#{ T(cz.sweb.pichlik.springioc.spel.Color).RED}" />
</bean>
Tuesday 28 May 13
IoC zbytek
Tuesday 28 May 13
Dědičnost
Tuesday 28 May 13
- sdileni definice vlastností mezi vice beanamy
- nemá nic společného s objektovou hierarchií
- společné property je možné přepsat v konkrétní beane
Integrace s existujícím kódem
Tuesday 28 May 13
Bean collecting
• “Sběr” objektů určitého typu
• Světlá strana autowiringu
Tuesday 28 May 13
- umoznuje dosahovat dynamicke extensibility aplikace
- podpora XML i anotaci
Anotace @Required
• Hlídá nastavení závislostí
• využití v kombinaci s XML
public class Bean {
	 private String foo;
	 @Required
	 public void setFoo(String foo) {
	 	 this.foo = foo;
	 } 	
}
<bean class="Bean">
<!--
Missing declaration
foo property
-->
</bean>
Tuesday 28 May 13
- predchazi NPE, kontainter selze pri bootu na chybejici zavislost
Nepřímé závislosti
Tuesday 28 May 13
- 3rd party nebo legacy kod
- pouzivat obezretne (v kodu neco smrdi)
Cyklické závislosti
• Vyvarujte se jich
• Špatný návrh API
• IoC kontejner dokáže částečně řešit
Tuesday 28 May 13
- fakci pouze pro setter injection
Profily
Tuesday 28 May 13
Spring Bean Definition profiles
• Bean definition might be defined
in a context activated on demand
• Context may represent an
environment or a strategy
• Multiple profiles might be
activated
Tuesday 28 May 13
Real/Mock example
...
<beans profile="real-backends">
<mongo:mongo id="mongo" replica-set="${mongodb.replicaSet}">
<mongo:options
connect-timeout="${mongodb.connectTimeout}"
socket-timeout="${mongodb.socketTimeout}"
write-timeout="${mongodb.writeTimeout}"
write-number="${mongodb.writeNumber}"
auto-connect-retry="true"
socket-keep-alive="true"
/>
</mongo:mongo>
</beans>
<beans profile="mocked-backends">
<bean id="mongo" class="com.mongodb.Mongo" factory-bean="fongo" factory-method="getMongo"/>
<bean id="fongo" class="com.foursquare.fongo.Fongo">
<constructor-arg value="gdc"></constructor-arg>
</bean>
</beans>
Tuesday 28 May 13
Profile servlet aktivace
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-
app_2_4.xsd">
...
<!--
Activate profile with real-backends. This profile contains beans configured
against the real backend and not mocks. The profile might be changed during
integration tests where mocked backends are used.
-->
<context-param>
<param-name>spring.profiles.default</param-name>
<param-value>real-backends</param-value>
</context-param>
...
Tuesday 28 May 13
Profile aktivace v int. test
/**
* Common superclass for integration tests. This class turns on mocked backends.
*/
public abstract class AbstractWebappIntegrationTest extends AbstractIntegrationTest {
...
private static final String MOCKED_BACKENDS_PROFILE_NAME = "mocked-backends";
/**
* Activates profile with mocked
*/
@BeforeClass
public static final void activateMockedBackends(){
log.warn("Activating profile with mocked backends '{}'", MOCKED_BACKENDS_PROFILE_NAME);
System.setProperty("spring.profiles.active", MOCKED_BACKENDS_PROFILE_NAME);
}
...
}
Tuesday 28 May 13
Aktivace profilu
• Context ini param in web.xml
• spring.profiles.default
• spring.profiles.active
• Programmatically
• ConfigurableEnvironment.setActiveProfiles()
• System property
• spring.profiles.active
Tuesday 28 May 13
Profile gotchas
• Musí být definován na konci XML
souboru
• Beany nejsou ani parsovány pokud
není profil aktivní
• Profil default může být použit jako
výchozí
• Alternativa k spring.profiles.default
Tuesday 28 May 13
Může vést k tomu, že pokud není profil zapnutý, nevíme jestli je vůbec daná část XML správně
Více o profilech
• http://blog.springsource.com/
2011/02/11/spring-
framework-3-1-m1-released/
• http://blog.springsource.org/
2011/02/14/spring-3-1-m1-
introducing-profile/
Tuesday 28 May 13
Praktické cvičení
Tuesday 28 May 13
1.) Nadefinujte nekolik bean Book v XML
2.) Upravte implementaci MemoryBookStoreDao, aby se automaticky
sebraly beany typu Book do Listu
3.) Presunte konfiguraci cesty pro FileSystemBookStoreDao do Properties
souboru
4.) Overte testem, ze obe implementace MemoryBookStoreDao po teto
zmene funguji
Ukazka - autowiringu na objektech, ktere nejsou beany
Tuesday 28 May 13
Čeho se vyvarovat
Tuesday 28 May 13
Programový bean lookup
• Používat velice obezřetně!
• Uvnitř bean speciálně
• NPE
• Nepřímé závislosti
Tuesday 28 May 13
- pouze mimo IoC kontext
- prakticke opodstatneni legacy kod a nebo problem singleton vs. prototyp
Statické holdery
• Funguje jenom pro singleton beany
• Znemožňuje reload instance
Tuesday 28 May 13
Vykutálený pomocník
• Musí být inicializován jako první
• Obchází DI
• WebApplicationContextUtils
Tuesday 28 May 13
Závěrečná doporučení
Tuesday 28 May 13
• Předejděte náhodnému mixování XML a
anotací
• Používejte @Qualifier pokud si nejste jistí
• V případě XML použijte @Required
• Nepoužívejte programový lookup bean pokud
to neni nezbytně nutné
• Pozor na mixování singleton a prototype
scope
Tuesday 28 May 13

More Related Content

Similar to Spring ioc-advanced

MoroSystems na ostravském CZJUGu o Apache Wicket
MoroSystems na ostravském CZJUGu o Apache WicketMoroSystems na ostravském CZJUGu o Apache Wicket
MoroSystems na ostravském CZJUGu o Apache WicketTomáš Páral
 
Dependency injection v Nette 2.1 prakticky
Dependency injection v Nette 2.1 praktickyDependency injection v Nette 2.1 prakticky
Dependency injection v Nette 2.1 praktickyFilip Procházka
 
MicroKernel - aneb špatný název pro Helper (5. sraz přátel Symfony v Praze)
MicroKernel - aneb špatný název pro Helper (5. sraz přátel Symfony v Praze)MicroKernel - aneb špatný název pro Helper (5. sraz přátel Symfony v Praze)
MicroKernel - aneb špatný název pro Helper (5. sraz přátel Symfony v Praze)Martin Zeman
 
MicroKernel aneb spatny nazev pro Helper (5. sraz pratel Symfony)
MicroKernel aneb spatny nazev pro Helper (5. sraz pratel Symfony)MicroKernel aneb spatny nazev pro Helper (5. sraz pratel Symfony)
MicroKernel aneb spatny nazev pro Helper (5. sraz pratel Symfony)Péhápkaři
 
CRCE - přehled datového modelu a vybraná API
CRCE - přehled datového modelu a vybraná APICRCE - přehled datového modelu a vybraná API
CRCE - přehled datového modelu a vybraná APIPremek Brada
 
Nette framework - How to compile an extensible di container
Nette framework - How to compile an extensible di containerNette framework - How to compile an extensible di container
Nette framework - How to compile an extensible di containerFilip Procházka
 
Easymock
EasymockEasymock
EasymockKeyup
 
Rozšiřitelnost ASP.NET MVC
Rozšiřitelnost ASP.NET MVCRozšiřitelnost ASP.NET MVC
Rozšiřitelnost ASP.NET MVCtopascz
 
Použití Next.js a Reactí UI khinihovny v aplikaci
Použití Next.js a Reactí UI khinihovny v aplikaciPoužití Next.js a Reactí UI khinihovny v aplikaci
Použití Next.js a Reactí UI khinihovny v aplikaciMartin Krištof
 
Rozšiřitelnost ASP.NET MVC
Rozšiřitelnost ASP.NET MVCRozšiřitelnost ASP.NET MVC
Rozšiřitelnost ASP.NET MVCtopascz
 
Miroslav Bajtoš - Nativní async/await v Node.js - už tam jsme?
Miroslav Bajtoš - Nativní async/await v Node.js - už tam jsme?Miroslav Bajtoš - Nativní async/await v Node.js - už tam jsme?
Miroslav Bajtoš - Nativní async/await v Node.js - už tam jsme?Develcz
 
Doctrine: co dělat, když entity nestačí
Doctrine: co dělat, když entity nestačíDoctrine: co dělat, když entity nestačí
Doctrine: co dělat, když entity nestačíFilip Procházka
 

Similar to Spring ioc-advanced (14)

Mesour DataGrid
Mesour DataGridMesour DataGrid
Mesour DataGrid
 
MoroSystems na ostravském CZJUGu o Apache Wicket
MoroSystems na ostravském CZJUGu o Apache WicketMoroSystems na ostravském CZJUGu o Apache Wicket
MoroSystems na ostravském CZJUGu o Apache Wicket
 
Dependency injection v Nette 2.1 prakticky
Dependency injection v Nette 2.1 praktickyDependency injection v Nette 2.1 prakticky
Dependency injection v Nette 2.1 prakticky
 
Django
DjangoDjango
Django
 
MicroKernel - aneb špatný název pro Helper (5. sraz přátel Symfony v Praze)
MicroKernel - aneb špatný název pro Helper (5. sraz přátel Symfony v Praze)MicroKernel - aneb špatný název pro Helper (5. sraz přátel Symfony v Praze)
MicroKernel - aneb špatný název pro Helper (5. sraz přátel Symfony v Praze)
 
MicroKernel aneb spatny nazev pro Helper (5. sraz pratel Symfony)
MicroKernel aneb spatny nazev pro Helper (5. sraz pratel Symfony)MicroKernel aneb spatny nazev pro Helper (5. sraz pratel Symfony)
MicroKernel aneb spatny nazev pro Helper (5. sraz pratel Symfony)
 
CRCE - přehled datového modelu a vybraná API
CRCE - přehled datového modelu a vybraná APICRCE - přehled datového modelu a vybraná API
CRCE - přehled datového modelu a vybraná API
 
Nette framework - How to compile an extensible di container
Nette framework - How to compile an extensible di containerNette framework - How to compile an extensible di container
Nette framework - How to compile an extensible di container
 
Easymock
EasymockEasymock
Easymock
 
Rozšiřitelnost ASP.NET MVC
Rozšiřitelnost ASP.NET MVCRozšiřitelnost ASP.NET MVC
Rozšiřitelnost ASP.NET MVC
 
Použití Next.js a Reactí UI khinihovny v aplikaci
Použití Next.js a Reactí UI khinihovny v aplikaciPoužití Next.js a Reactí UI khinihovny v aplikaci
Použití Next.js a Reactí UI khinihovny v aplikaci
 
Rozšiřitelnost ASP.NET MVC
Rozšiřitelnost ASP.NET MVCRozšiřitelnost ASP.NET MVC
Rozšiřitelnost ASP.NET MVC
 
Miroslav Bajtoš - Nativní async/await v Node.js - už tam jsme?
Miroslav Bajtoš - Nativní async/await v Node.js - už tam jsme?Miroslav Bajtoš - Nativní async/await v Node.js - už tam jsme?
Miroslav Bajtoš - Nativní async/await v Node.js - už tam jsme?
 
Doctrine: co dělat, když entity nestačí
Doctrine: co dělat, když entity nestačíDoctrine: co dělat, když entity nestačí
Doctrine: co dělat, když entity nestačí
 

More from Roman Pichlík

MongoDB for Java Developers
MongoDB for Java DevelopersMongoDB for Java Developers
MongoDB for Java DevelopersRoman Pichlík
 
Nosql from java developer pov
Nosql from java developer povNosql from java developer pov
Nosql from java developer povRoman Pichlík
 
Spring framework - J2EE S Lidskou Tvari
Spring framework - J2EE S Lidskou TvariSpring framework - J2EE S Lidskou Tvari
Spring framework - J2EE S Lidskou TvariRoman Pichlík
 
Dependency Injection Frameworky
Dependency Injection FrameworkyDependency Injection Frameworky
Dependency Injection FrameworkyRoman Pichlík
 

More from Roman Pichlík (8)

Spring MVC
Spring MVCSpring MVC
Spring MVC
 
Spring integration
Spring integrationSpring integration
Spring integration
 
Spring dao
Spring daoSpring dao
Spring dao
 
Spring Web Services
Spring Web ServicesSpring Web Services
Spring Web Services
 
MongoDB for Java Developers
MongoDB for Java DevelopersMongoDB for Java Developers
MongoDB for Java Developers
 
Nosql from java developer pov
Nosql from java developer povNosql from java developer pov
Nosql from java developer pov
 
Spring framework - J2EE S Lidskou Tvari
Spring framework - J2EE S Lidskou TvariSpring framework - J2EE S Lidskou Tvari
Spring framework - J2EE S Lidskou Tvari
 
Dependency Injection Frameworky
Dependency Injection FrameworkyDependency Injection Frameworky
Dependency Injection Frameworky
 

Spring ioc-advanced

  • 1. Spring framework Motto: Musíte rozbít vejce když chcete udělat omeletu Spring framework training materials by Roman Pichlík is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. Tuesday 28 May 13
  • 3. Agenda • Hierarchická konfigurace • Dynamické nahrávání kontextů • PropertyEditory • Validace • SPEL Tuesday 28 May 13
  • 6. Property placeholders • Konfigurace mimo XML • Atributy spjaté s prostředím • databáze, HTTP endpointy atd. • známe až v deploy time Tuesday 28 May 13 - Operations opravdu neradi editují XML v zanorenem JARu na filesystemu
  • 7. Příklad @Component public class MyAnnotatedBean { @Value("${username}") private String username; public String getUsername() { return username; } } Tuesday 28 May 13
  • 8. Složitější případ užití • Proč jeden soubor nestačí • různá prostředí • testy, produkce, developer stroj • chceme definovat smart defaults Tuesday 28 May 13
  • 9. Konfigurační hierarchie • Každá komponenta může definovat default hodnoty • Aplikace definuje svoje default hodnoty • Prostředí definuje svoje hodnoty Component defaults Application defaults Environment values přepisuje Tuesday 28 May 13 System.properties override
  • 10. Provedení • Pořadí definice určuje prioritu • Dynamické načítání z classpath • Chybějící properties soubory se ignorují • přenositelnost <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="ignoreResourceNotFound" value="true" /> <property name="ignoreUnresolvablePlaceholders" value="true" /> <property name="locations"> <list> <value>classpath*:META-INF/componentDefault.properties</value> <value>classpath:META-INF/applicationDefault.properties</value> <value>file:/opt/configuration/deployment.properties</value> </list> </property> </bean> Tuesday 28 May 13
  • 12. Resource • Spring abstrakce pro přístup k souborům v různém prostředí Prefix Příklad Vysvětlivka classpath: classpath:com/myapp/config.xml Nahravá se z classpath file: file:/data/config.xml Nahrává se z FS http: http://myserver/logo.png Nahrává přes URL Bez prefixu /data/config.xml Závisí na typu ApplicationContext Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt"); <bean id="myBean" class="..."> <property name="template" value="some/resource/path/myTemplate.txt"/> </bean> Tuesday 28 May 13
  • 13. Wildcards & Ant path /WEB-INF/*-context.xml classpath:com/mycompany/**/applicationContext.xml classpath*:META-INF/*-beans.xml • Wildcard * • nahrání více resourců • komplexní boot aplikace Tuesday 28 May 13
  • 15. Motivace • Pouze ze začátku vystačí jeden bean definition file na aplikace • nepraktické • chceme oddělit definici bean podle komponenty nebo typu • přehlednost Tuesday 28 May 13
  • 16. Využití Resource abstrakce • Definujte kontexty v předem definované cestě • META-INF/company/spring • Pojmenované s pevným suffixem • *-applicationContext.xml Tuesday 28 May 13
  • 17. Inicializace • Automatické načtení všech bean definic na classpath • usnadňuje přidávání nových kontextů • umožňuje dynamické načítání podle toho jak je classpath sestavena • někdy méně přehledné String path = "classpath*:META-INF/company/*-applicationContext.xml"; new ClassPathXmlApplicationContext(path); <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath*:META-INF/company/*-applicationContext.xml </param-value> </context-param> Tuesday 28 May 13
  • 18. Strategický context • Definuje infrastrukturní beany používané v celé aplikaci • DataSource, Transakční manažer, HibernateSessionFactory atd. • Může mít různou podobu pro různá prostředí • Testy, Produkce, Aplikační server Tuesday 28 May 13 - nejdulezitejsi beany na jednom miste - lze pouzit import
  • 20. java.beans.PropertyEditor • Rozhraní pro konverzi String –> Datový typ ve Springu • Používá se • inicializace kontejneru a nastavování bean values • Spring MVC konverze z query params (?name=dagi&age=31) Tuesday 28 May 13
  • 21. public class BeanWithSpecialDate { private SpecialDateType specialDateType; public SpecialDateType getSpecialDateType() { return specialDateType; } public void setSpecialDateType(SpecialDateType specialDateType) { this.specialDateType = specialDateType; } } public class SpecialDateType { private final Date date; public SpecialDateType(Date date) { this.date = date; } public Date getDate() { return date; } } public class SpecialDatePropertyEditor extends PropertyEditorSupport{ @Override public void setAsText(String text) throws IllegalArgumentException { SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy"); try { setValue(new SpecialDateType(sdf.parse(text))); } catch (ParseException e) { throw new IllegalArgumentException("Cannot parse date", e); } } } <bean class="cz.sweb.pichlik.springioc.propertyeditor.BeanWithSpecialDate"> <property name="specialDateType" value="01-01-2000" /> </bean> <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer"> <property name="customEditors"> <map> <entry key="cz.sweb.pichlik.springioc.propertyeditor.SpecialDateType" value="cz.sweb.pichlik.springioc.propertyeditor.SpecialDatePropertyEditor"/> </map> </property> </bean> je definovaná sespeciálním typem uvedeným jako String Tuesday 28 May 13
  • 22. public class BeanWithSpecialDate { private SpecialDateType specialDateType; public SpecialDateType getSpecialDateType() { return specialDateType; } public void setSpecialDateType(SpecialDateType specialDateType) { this.specialDateType = specialDateType; } } public class SpecialDateType { private final Date date; public SpecialDateType(Date date) { this.date = date; } public Date getDate() { return date; } } public class SpecialDatePropertyEditor extends PropertyEditorSupport{ @Override public void setAsText(String text) throws IllegalArgumentException { SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy"); try { setValue(new SpecialDateType(sdf.parse(text))); } catch (ParseException e) { throw new IllegalArgumentException("Cannot parse date", e); } } } <bean class="cz.sweb.pichlik.springioc.propertyeditor.BeanWithSpecialDate"> <property name="specialDateType" value="01-01-2000" /> </bean> <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer"> <property name="customEditors"> <map> <entry key="cz.sweb.pichlik.springioc.propertyeditor.SpecialDateType" value="cz.sweb.pichlik.springioc.propertyeditor.SpecialDatePropertyEditor"/> </map> </property> </bean> o jehož konverzi se stará PropertyEditor Tuesday 28 May 13
  • 23. public class BeanWithSpecialDate { private SpecialDateType specialDateType; public SpecialDateType getSpecialDateType() { return specialDateType; } public void setSpecialDateType(SpecialDateType specialDateType) { this.specialDateType = specialDateType; } } public class SpecialDateType { private final Date date; public SpecialDateType(Date date) { this.date = date; } public Date getDate() { return date; } } public class SpecialDatePropertyEditor extends PropertyEditorSupport{ @Override public void setAsText(String text) throws IllegalArgumentException { SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy"); try { setValue(new SpecialDateType(sdf.parse(text))); } catch (ParseException e) { throw new IllegalArgumentException("Cannot parse date", e); } } } <bean class="cz.sweb.pichlik.springioc.propertyeditor.BeanWithSpecialDate"> <property name="specialDateType" value="01-01-2000" /> </bean> <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer"> <property name="customEditors"> <map> <entry key="cz.sweb.pichlik.springioc.propertyeditor.SpecialDateType" value="cz.sweb.pichlik.springioc.propertyeditor.SpecialDatePropertyEditor"/> </map> </property> </bean> patřičně zaregistrovaný Tuesday 28 May 13
  • 24. public class BeanWithSpecialDate { private SpecialDateType specialDateType; public SpecialDateType getSpecialDateType() { return specialDateType; } public void setSpecialDateType(SpecialDateType specialDateType) { this.specialDateType = specialDateType; } } public class SpecialDateType { private final Date date; public SpecialDateType(Date date) { this.date = date; } public Date getDate() { return date; } } public class SpecialDatePropertyEditor extends PropertyEditorSupport{ @Override public void setAsText(String text) throws IllegalArgumentException { SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy"); try { setValue(new SpecialDateType(sdf.parse(text))); } catch (ParseException e) { throw new IllegalArgumentException("Cannot parse date", e); } } } <bean class="cz.sweb.pichlik.springioc.propertyeditor.BeanWithSpecialDate"> <property name="specialDateType" value="01-01-2000" /> </bean> <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer"> <property name="customEditors"> <map> <entry key="cz.sweb.pichlik.springioc.propertyeditor.SpecialDateType" value="cz.sweb.pichlik.springioc.propertyeditor.SpecialDatePropertyEditor"/> </map> </property> </bean> je definovaná sespeciálním typem uvedeným jako String o jehož konverzi se stará PropertyEditor patřičně zaregistrovaný Tuesday 28 May 13
  • 26. • Řešeno přes Bean Validation • JSR 303 • Možnost použití přes různé int. • org.springframework.validation • javax.validation.Validator • Integrace do Spring MVC Tuesday 28 May 13
  • 27. @Service public class MyService { @Autowired private Validator validator; public void doSomethingWithPerson(Person person){ Set<ConstraintViolation<Person>> resultOfValidation = validator.validate(person); for (ConstraintViolation<Person> constraintViolation : resultOfValidation) { throw new IllegalArgumentException(constraintViolation.getMessage()); } } } public class Person { @DecimalMax(value="110", message="Maximum age is 110") @DecimalMin(value="0", message="Minimum age is 0") private int age; @NotNull @Valid private Address address; public Person() { super(); } public Person(int age, Address address) { super(); this.age = age; this.address = address; } } <bean class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" /> používávalidátor validuje JSR 303 validační anotace Tuesday 28 May 13
  • 29. Spring EL • Expression Language • operátory, volání metod, proměnné a mnohem víc • přímé použití jako EL • definice bean Tuesday 28 May 13
  • 30. Použití • Jako EL ve vlastní aplikaci • V rámcí definice bean • Lze použít i v anotaci @Value ExpressionParser p = new SpelExpressionParser(); Expression exp = p.parseExpression("'Hello World'.concat('!')"); String message = (String) exp.getValue(); <bean id="numberGuess" class="org.spring.samples.NumberGuess"> <property name="randomNumber" value="#{ T(java.lang.Math).random() * 100.0 }"/> </bean> Tuesday 28 May 13 používání v definici bean vede k programování na úrovni XML => Ant syndrom
  • 31. Vhodné použití • Enums, Constanty v XML <bean class="cz.sweb.pichlik.springioc.spel.ColorBean"> <property name="color" value="#{ T(cz.sweb.pichlik.springioc.spel.Color).RED}" /> </bean> Tuesday 28 May 13
  • 33. Dědičnost Tuesday 28 May 13 - sdileni definice vlastností mezi vice beanamy - nemá nic společného s objektovou hierarchií - společné property je možné přepsat v konkrétní beane
  • 34. Integrace s existujícím kódem Tuesday 28 May 13
  • 35. Bean collecting • “Sběr” objektů určitého typu • Světlá strana autowiringu Tuesday 28 May 13 - umoznuje dosahovat dynamicke extensibility aplikace - podpora XML i anotaci
  • 36. Anotace @Required • Hlídá nastavení závislostí • využití v kombinaci s XML public class Bean { private String foo; @Required public void setFoo(String foo) { this.foo = foo; } } <bean class="Bean"> <!-- Missing declaration foo property --> </bean> Tuesday 28 May 13 - predchazi NPE, kontainter selze pri bootu na chybejici zavislost
  • 37. Nepřímé závislosti Tuesday 28 May 13 - 3rd party nebo legacy kod - pouzivat obezretne (v kodu neco smrdi)
  • 38. Cyklické závislosti • Vyvarujte se jich • Špatný návrh API • IoC kontejner dokáže částečně řešit Tuesday 28 May 13 - fakci pouze pro setter injection
  • 40. Spring Bean Definition profiles • Bean definition might be defined in a context activated on demand • Context may represent an environment or a strategy • Multiple profiles might be activated Tuesday 28 May 13
  • 41. Real/Mock example ... <beans profile="real-backends"> <mongo:mongo id="mongo" replica-set="${mongodb.replicaSet}"> <mongo:options connect-timeout="${mongodb.connectTimeout}" socket-timeout="${mongodb.socketTimeout}" write-timeout="${mongodb.writeTimeout}" write-number="${mongodb.writeNumber}" auto-connect-retry="true" socket-keep-alive="true" /> </mongo:mongo> </beans> <beans profile="mocked-backends"> <bean id="mongo" class="com.mongodb.Mongo" factory-bean="fongo" factory-method="getMongo"/> <bean id="fongo" class="com.foursquare.fongo.Fongo"> <constructor-arg value="gdc"></constructor-arg> </bean> </beans> Tuesday 28 May 13
  • 42. Profile servlet aktivace <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web- app_2_4.xsd"> ... <!-- Activate profile with real-backends. This profile contains beans configured against the real backend and not mocks. The profile might be changed during integration tests where mocked backends are used. --> <context-param> <param-name>spring.profiles.default</param-name> <param-value>real-backends</param-value> </context-param> ... Tuesday 28 May 13
  • 43. Profile aktivace v int. test /** * Common superclass for integration tests. This class turns on mocked backends. */ public abstract class AbstractWebappIntegrationTest extends AbstractIntegrationTest { ... private static final String MOCKED_BACKENDS_PROFILE_NAME = "mocked-backends"; /** * Activates profile with mocked */ @BeforeClass public static final void activateMockedBackends(){ log.warn("Activating profile with mocked backends '{}'", MOCKED_BACKENDS_PROFILE_NAME); System.setProperty("spring.profiles.active", MOCKED_BACKENDS_PROFILE_NAME); } ... } Tuesday 28 May 13
  • 44. Aktivace profilu • Context ini param in web.xml • spring.profiles.default • spring.profiles.active • Programmatically • ConfigurableEnvironment.setActiveProfiles() • System property • spring.profiles.active Tuesday 28 May 13
  • 45. Profile gotchas • Musí být definován na konci XML souboru • Beany nejsou ani parsovány pokud není profil aktivní • Profil default může být použit jako výchozí • Alternativa k spring.profiles.default Tuesday 28 May 13 Může vést k tomu, že pokud není profil zapnutý, nevíme jestli je vůbec daná část XML správně
  • 46. Více o profilech • http://blog.springsource.com/ 2011/02/11/spring- framework-3-1-m1-released/ • http://blog.springsource.org/ 2011/02/14/spring-3-1-m1- introducing-profile/ Tuesday 28 May 13
  • 48. 1.) Nadefinujte nekolik bean Book v XML 2.) Upravte implementaci MemoryBookStoreDao, aby se automaticky sebraly beany typu Book do Listu 3.) Presunte konfiguraci cesty pro FileSystemBookStoreDao do Properties souboru 4.) Overte testem, ze obe implementace MemoryBookStoreDao po teto zmene funguji Ukazka - autowiringu na objektech, ktere nejsou beany Tuesday 28 May 13
  • 50. Programový bean lookup • Používat velice obezřetně! • Uvnitř bean speciálně • NPE • Nepřímé závislosti Tuesday 28 May 13 - pouze mimo IoC kontext - prakticke opodstatneni legacy kod a nebo problem singleton vs. prototyp
  • 51. Statické holdery • Funguje jenom pro singleton beany • Znemožňuje reload instance Tuesday 28 May 13
  • 52. Vykutálený pomocník • Musí být inicializován jako první • Obchází DI • WebApplicationContextUtils Tuesday 28 May 13
  • 54. • Předejděte náhodnému mixování XML a anotací • Používejte @Qualifier pokud si nejste jistí • V případě XML použijte @Required • Nepoužívejte programový lookup bean pokud to neni nezbytně nutné • Pozor na mixování singleton a prototype scope Tuesday 28 May 13