2010-10-14 - présentation google guice par mathieu carbou

47
Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected] Dependency Injection Guice with...

Upload: montreal-jug

Post on 02-Jul-2015

945 views

Category:

Technology


0 download

DESCRIPTION

http://www.montreal-jug.org/

TRANSCRIPT

Page 1: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Dependency Injection

Guicewith...

Page 2: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

About me

Mathieu Carbou Expert Java Developer + 6 years Open-Source projects Code design, Web, Testing, Maven, Spring, WS,

JMS, EDA, OSGI , Security, Hibernate, .... … and Google Guice !

http://code.mycila.com

http://blog.mycila.com

http://www.testatoo.org

Page 3: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

About the next hour

Pre-DI anti-patterns Evolutions in the Java World DI advantages A little word about Spring... … and a long long time about Guice !

Page 4: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Pre-DI Anti-Patterns

Manual instanciation

public final class SignupService { public void signup(User user) { EmailService emailService = new EmailService(); emailService.setHost("smtp.company.com"); emailService.setPort(25); emailService.send( "[email protected]", user.getEmail(), "Welcome to Killer App !"); }}

Page 5: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Pre-DI Anti-Patterns

Factory pattern

public final class SignupService { public void signup(User user) { EmailService emailService =

EmailServiceFactory.getEmailService(); emailService.send( "[email protected]", user.getEmail(), "Welcome to Killer App !"); }}

Page 6: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Pre-DI Anti-Patterns

Service locator

public void signup(User user) { // retreived from JNDI for example ServiceLocator serviceLocator = getServiceLocator(); EmailService emailService = (EmailService)

serviceLocator.getService("emailService"); emailService.send( "[email protected]", user.getEmail(), "Welcome to Killer App !");}

Page 7: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Pre-DI Anti-Patterns

Bean factory

public void signup(User user) { // retreived Spring's bean factory BeanFactory beanFactory = getBeanFactory(); EmailService emailService =

(EmailService) beanFactory.getBean("emailService"); emailService.send( "[email protected]", user.getEmail(), "Welcome to Killer App !");}

Page 8: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Pre-DI Anti-Patterns

Design issues Strong coupling (locator, factory, identifier) No isolation Difficult to test, refactor and maintain

SignupService MailService

ServiceLocator

UserService UserRepository UserRepository

depends

depends

depends

depends

Page 9: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Pre-DI Anti-Patterns

Potential issues Bad responsibility for client and user classes Static references never garbadged-collected Static shared access issues (concurrency) Static lazy initialization often badly coded

Page 10: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Pre-DI Anti-Patterns

public final class MyFactory {

private static EmailService EMAIL_SERVICE;

public static EmailService getEmailService() { if(EMAIL_SERVICE == null) { EMAIL_SERVICE = new EmailService(); //object initalization } return EMAIL_SERVICE; }

}

Page 11: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Pre-DI Anti-Patterns

public final class MyFactory {

private static EmailService EMAIL_SERVICE;

public static synchronized EmailService getEmailService() { if(EMAIL_SERVICE == null) { EMAIL_SERVICE = new EmailService(); //object initalization } return EMAIL_SERVICE; }

}

Page 12: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Pre-DI Anti-Patterns

public final class MyFactory {

private MyFactory() {}

public static EmailService getEmailService() { return LazyInit.EMAIL_SERVICE; }

private static final class LazyInit { private static final EmailService EMAIL_SERVICE

= new EmailService(); }}

Page 13: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Evolutions

Metadata representations XML Annotations

Misconception about annotations

Annotations are metadata within classes introducing no dependencies at runtime. A class can be resolved even if its annotations are not in the classpath !

Page 14: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Evolutions

ByteCode manipulation (ASM, proxy, ...) JSR250 (already in JDK6, commes from J2EE)

@Resource

@PostConstruct

@PreDestroy

JSR330 (next JDK, jar available) @Inject

@Provider

@Named

@Singleton

@Scope

Page 15: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Evolutions

Generics (type literals) List<Employee> != List<User>

Some DI frameworks till rely on Class (Spring) May crash at runtime (type erasure) !

New DI frameworks use TypeLiteral (Guice) Errors caugth at compile time !

Page 16: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Evolutions

Example:

public final class FireService {

final List<Employee> employees;

@Inject FireService(List<Employee> employees) { this.employees = employees; }

public void fireAll() { for (Employee employee : employees) employee.fire(); }}

Page 17: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Evolutions

Guice: Compile error !

Spring (xml): compiles, but fails at runtime !

final class FireModule extends AbstractModule { protected void configure() { bind(new TypeLiteral<List<Employee>>(){})

.toInstance(Arrays.asList(new User())); }}

<bean name="fireService"class="com.mycompany.killerapp.FireService">

<constructor-arg> <list> <bean class="com.mycompany.killerapp.User"/> </list> </constructor-arg></bean>

Page 18: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

DI Definition

A dependant is contacted by its dependencies

Hollywood principle: Don't call me, I'll call you

Page 19: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

DI Definition

Example:

public final class FireService {

final List<Employee> employees;

@Inject FireService(List<Employee> employees) { this.employees = employees; }

public void fireAll() { for (Employee employee : employees) employee.fire(); }}

Page 20: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

DI Advantages

Easier testing & refactoring Easier maintenance Loose coupling Manage object lifetime Better design and use (interfaces) Hide implementation details Write less code (and less bugs)

Page 21: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

About Spring Framework

Everyone knows it You can compare

Guice != Spring Guice = Advanced DI framework Spring = Integration Framework (JMX, JMS, JDBC,

TX, Hibernate, ...) built upon a DI stack

You can use Spring classes with Guice

Page 22: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Google Guice !

Open-Sourced by Google First public release in 2007 http://code.google.com/p/google-guice/

Project's lead: Bob Lee Cofounder of AOP Alliance Creator of JAdvise and Dynaop Strong AOP background

Page 23: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Google Guice !

Version 3 to be released soon

Standardized DI annotations (JSR330)

Focus on: Easy to use Best DI capabilities

Not an integration framework

Page 24: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Google Guice Ecosystem

Guice Servlets (DSL, DI and lifetime management for servlets and filters)

<listener> <listener-class> com.company.web.guice.GuiceConfig </listener-class></listener><filter> <filter-name>Guice Filter</filter-name> <filter-class> com.google.inject.servlet.GuiceFilter </filter-class></filter><filter-mapping> <filter-name>Guice Filter</filter-name> <url-pattern>/*</url-pattern></filter-mapping>

Page 25: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Google Guice Ecosystem

Guice Servlets (DSL, DI and lifetime management for servlets and filters)

protected void configureServlets() { Map<String, String> params = new HashMap<String, String>();

/* Shirio Security */ bind(IniShiroFilter.class).in(Scopes.SINGLETON); filter("/*").through(IniShiroFilter.class);

/* Wicket */ params.put(WicketFilter.FILTER_MAPPING_PARAM, "/*"); filter("/page/*").through(WicketGuiceFilter.class, params); bind(WebApplication.class).to(MyApplication.class);

/* Jersey */ serve("/rest/*").with(GuiceContainer.class, params);}

Page 26: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Google Guice Ecosystem

Guice Persistence (Hibernate, JPA, DB4O, ...)

protected void configurePersistence() { workAcross(UnitOfWork.TRANSACTION).usingJpa("c4sJpaUnit"); bind(DataSource.class) .toProvider(fromJndi(DataSource.class, "jdbc/c4sDS")) .in(Singleton.class); bind(PlayerRepository.class) .to(JpaPlayerRepository.class) .in(Singleton.class); bind(TeamRepository.class) .to(JpaTeamRepository.class) .in(Singleton.class);}

Page 27: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Google Guice Ecosystem

Guice Persistence (Dynamic finders)

public interface TeamFinder { @Finder(query="from Team") List<Team> allTeams();}

Page 28: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Google Guice Ecosystem

Guice Jndi

class SqlModule extends AbstractModule { protected void configure() { bind(UserRepository.class).to(SQLUserRepository.class);bind(DataSource.class)

.toProvider(fromJndi(DataSource.class, "jdbc/h2DB"))

.in(Singleton.class);

}}

Page 29: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Google Guice Ecosystem

Spring Integration Assisted inject (contextual DI)

interface PaymentFactory {Payment create(Date startDate, Money amount);

}

// DI configurationbind(Payment.class).to(PaymentImpl.class);bind(PaymentFactory.class)

.toProvider(newFactory(PaymentFactory.class, RealPayment.class));

// user codePayement pay = factory.create(today, amount);

Page 30: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Google Guice Ecosystem

Projects extending Guice capabilities: Peaberry (OSGI) Mycila-testing Guiceyfruit (JSR250, JNDI, ...)

Mycila-guice (JSR250, scopes, module discovery, …)

GuiceBerry [...]

Page 31: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Google Guice Integration

Page 32: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Guice relative Books

Page 33: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Google Guice Advantages

Easier to use, test, maintain, refactor, learn Better power to complexity ratio than Spring Advanced DI concepts Favor good design

Immutability, valid objects Thread-safe object

No more java beans constraints Injectable DSL is possible

Page 34: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Google Guice Advantages

No string identifier No more conflicts No more responsability issue

No more XML ! Static and compile-time verification Plus many things we'll see in details now !

Page 35: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Dive into Guice

DI configuration (Java-based, DSL & Fluent API)

public final class SqlModule extends AbstractModule { @Override protected void configure() { bind(UserRepository.class).to(SQLUserRepository.class); bind(DataSource.class) .toProvider(fromJndi(DataSource.class,"jdbc/myDB")) .in(Singleton.class); } @Provides Connection connection(DataSource dataSource) throws SQLException { return dataSource.getConnection(); }}

Page 36: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Dive into Guice

Dependency identification: Key class Supports type literals and raw types Bindings annotations Static type checking Errors caught at compile time, not at runtime

Page 37: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Dive into Guice

Dependency identification

bind(Properties.class) .annotatedWith(named("app-settings")) .toProvider(fromJndi(Properties.class, "settings/app"));

bind(new TypeLiteral<GenericRepository<Employee>>(){}).to(EmployeeRepository.class);

--------------------------------------------------------------

Key key = Key.get(new TypeLiteral<GenericRepository<Employee>>(){});

GenericRepository<Employee> repo = injector.getInstance(key)

Properties props = injector.getInstance( Key.get(Properties, named("app-settings")))

Page 38: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Dive into Guice

Bootstrapping

Injector injector = Guice.createInjector(Stage.PRODUCTION, new MyModule(), new JSR250Module(), new SqlModule());

Page 39: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Dive into Guice

Injection points: Constructors, Fields, Methods

public class BasicTemplateService {

@Inject UserRepository repository private final Settings settings; @Inject public BasicTemplateService(Settings settings) { this.settings = settings; } @Inject @Named("/app/messages/user") void withMessageBundle(ResourceBundle rb) {

[...] }}

Page 40: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Dive into Guice

AOP support Easy All casual cases

Intercept: Methods Injections

Matchers Classes Methods

Page 41: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Dive into Guice

AOP support - InterceptorsbindInterceptor(

Matchers.inPackage(getPackage("com.company.repository")), Matchers.annotatedWith(Test.class), new MyAopAllianceInterceptor());

package com.company.repository;class MyRepository { @Test void intercepted() {}}

Page 42: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Dive into Guice

AOP support – Injection listeners

bindListener(Matchers.any(), new TypeListener() {

public <I> void hear(final TypeLiteral<I> type, final TypeEncounter<I> encounter) {

System.out.println("Meeting type: " + type);

encounter.register(new InjectionListener<I>() {

public void afterInjection(I injectee) { System.out.println("Type has been injected"); } }); }});

Page 43: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Dive into Guice

Providers Scope widening Delay construction

class CurrentLocale {

@Inject Provider<HttpServletRequest> request;

public Locale get() { [...] }}

Page 44: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Dive into Guice

Scopes Object lifetime management By default: no scope Allows objects to be garbadged-collected shortly

Misconception about singletons @Singleton IS a scope ! Should only considered when really needed Constructing new objects has no cost in Java

Page 45: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Dive into Guice

Scopes

bind(JamesBondMessage.class) .in(new ExpiringSingleton(10, SECONDS));

bindScope(Concurrent.class, new ConcurrentSingleton());bind(EnglishDataLoader.class).in(Concurrent.class);bind(FrenchDataLoader.class).in(Concurrent.class);

@Concurrentclass SpanishDataLoader {}

Page 46: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Dive into Guice

And also Module overriding

Modules.override(...).by()... Introspection API

Elements.getElements() binding.acceptVisitor() […]

Parent / Child injectors Private / Public bindings

Page 47: 2010-10-14 - Présentation Google Guice par Mathieu Carbou

Copyright © 2010 – Mathieu Carbou – Mycila.com - [email protected]

Guice questions ?