More Related Content
Similar to Google Guice presentation at Montreal JUG - October 2010
Similar to Google Guice presentation at Montreal JUG - October 2010 (20)
Google Guice presentation at Montreal JUG - October 2010
- 1. Dependency
Injection
with...
Guice
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 2. 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
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 3. 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 !
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 4. 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(
"killerapp@company.com",
user.getEmail(),
"Welcome to Killer App !");
}
}
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 5. Pre-DI Anti-Patterns
Factory pattern
public final class SignupService {
public void signup(User user) {
EmailService emailService =
EmailServiceFactory.getEmailService();
emailService.send(
"killerapp@company.com",
user.getEmail(),
"Welcome to Killer App !");
}
}
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 6. Pre-DI Anti-Patterns
Service locator
public void signup(User user) {
// retreived from JNDI for example
ServiceLocator serviceLocator = getServiceLocator();
EmailService emailService =
serviceLocator.getEmailService("emailService");
emailService.send(
"killerapp@company.com",
user.getEmail(),
"Welcome to Killer App !");
}
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 7. 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(
"killerapp@company.com",
user.getEmail(),
"Welcome to Killer App !");
}
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 8. Pre-DI Anti-Patterns
Design issues
Strong coupling (locator, factory, identifier)
No isolation
Difficult to test, refactor and maintain
SignupService depends MailService
depends
depends
ServiceLocator
depends
UserService UserRepository UserRepository
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 9. Pre-DI Anti-Patterns
Potential issues
Static references never garbadged-collected
Static shared access issues (concurrency)
Static lazy initialization often badly coded
Bad responsibility for client and user classes
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 10. 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 !
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 11. Evolutions
JSR250 (already in JDK6, commes from J2EE)
@Resource
@PostConstruct
@PreDestroy
JSR330 (next JDK, jar available)
@Inject
@Provider
@Named
@Singleton
@Scope
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 12. 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 !
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 13. 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();
}
}
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 14. Evolutions
Guice: Compile error !
final class FireModule extends AbstractModule {
protected void configure() {
bind(new TypeLiteral<List<Employee>>(){})
.toInstance(Arrays.asList(new User()));
}
}
Spring (xml): compiles, but fails at runtime !
<bean name="fireService"
class="com.mycompany.killerapp.FireService">
<constructor-arg>
<list>
<bean class="com.mycompany.killerapp.User"/>
</list>
</constructor-arg>
</bean>
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 15. DI Definition
A dependant is contacted by its dependencies
Hollywood principle: Don't call me, I'll call you
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 16. 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();
}
}
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 17. 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)
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 18. 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
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 19. 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
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 20. Google Guice !
Version 3 to be released soon
Standardized DI annotations (JSR330)
Focus on:
Easy to use
Best DI capabilities
Not an integration framework
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 21. 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>
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 22. 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);
}
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 23. 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);
}
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 24. Google Guice Ecosystem
Guice Persistence (Dynamic finders)
public interface TeamFinder {
@Finder(query="from Team")
List<Team> allTeams();
}
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 25. 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);
}
}
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 26. Google Guice Ecosystem
Spring Integration
Assisted inject (contextual DI)
interface PaymentFactory {
Payment create(Date startDate, Money amount);
}
// DI configuration
bind(Payment.class).to(PaymentImpl.class);
bind(PaymentFactory.class)
.toProvider(newFactory(PaymentFactory.class,
RealPayment.class));
// user code
Payement pay = factory.create(today, amount);
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 27. Google Guice Ecosystem
Projects extending Guice capabilities:
Peaberry (OSGI)
Mycila-testing
Guiceyfruit (JSR250, JNDI, ...)
Mycila-guice (JSR250, scopes, module discovery, …)
GuiceBerry
[...]
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 30. 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
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 31. 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 !
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 32. 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();
}
}
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 33. 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
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 34. 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")))
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 35. Dive into Guice
Bootstrapping
Injector injector = Guice.createInjector(
Stage.PRODUCTION,
new MyModule(), new JSR250Module(), new SqlModule());
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 36. 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) {
[...]
}
}
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 37. Dive into Guice
AOP support
Easy
All casual cases
Intercept:
Methods
Injections
Matchers
Classes
Methods
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 38. Dive into Guice
AOP support - Interceptors
bindInterceptor(
Matchers.inPackage(getPackage("com.company.repository")),
Matchers.annotatedWith(Test.class),
new MyAopAllianceInterceptor());
package com.company.repository;
class MyRepository {
@Test
void intercepted() {}
}
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 39. 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");
}
});
}
});
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 40. Dive into Guice
Providers
Scope widening
Delay construction
class CurrentLocale {
@Inject
Provider<HttpServletRequest> request;
public Locale get() {
[...]
}
}
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 41. 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
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 42. 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);
@Concurrent
class SpanishDataLoader {
}
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 43. Dive into Guice
And also
Module overriding
Modules.override(...).by()...
Introspection API
Elements.getElements()
binding.acceptVisitor()
[…]
Parent / Child injectors
Private / Public bindings
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com
- 44. Guice questions ?
Copyright © 2010 – Mathieu Carbou – Mycila.com - mathieu.carbou@gmail.com