Lidando com Java Obsoleto: Do Struts 1.0 ao CDI

Propaganda
Lidando com Java
Obsoleto: Do Struts 1.0
ao CDI
Java na Crista da Onda
Lidando com Java
Obsoleto: Do Struts 1.0
ao VRaptor com CDI
Java na Crista da Onda
David Robert
[email protected]
linkedin.com/in/davidrobert
Lidando com Java
Obsoleto
Struts & CDI
AMBIENTE
AMBIENTE
A long time ago in a galaxy far,
far away...
Manutenabilidade
Comprometida
❏ baixa coesão
❏ alto acoplamento
❏ código legado
JDBC
> 600 conexões
por requisição
Manutenabilidade
Comprometida
❏ baixa coesão
❏ alto acoplamento
❏ código legado
AMBIENTE
Como melhorar?
Reescrever ?
Reescrever ?
➢ ~ 700.000 linhas de código
(>200.000 de Java)
Reescrever ?
➢ ~ 700.000 linhas de código
(>200.000 de Java)
➢ O que fazer com as regras de
negocio? reescrever?
Reescrever ?
➢ ~ 700.000 linhas de código
(>200.000 de Java)
➢ O que fazer com as regras de
negocio? reescrever?
➢ Quanto tempo vai custar?
O beneficio vale a pena?
Como evoluir de maneira saudável?
Como evoluir de maneira saudável?
Baixo acoplamento
Alta Coesão
Testes!
CDI
public class ProdutoDao {
public void salvar(Produto produto) {
entityManager.persist(produto);
}
}
public class ProdutoDao {
private EntityManager entityManager;
public ProdutoDao(EntityManager em) {
this.entityManager = em;
}
public void salvar(Produto produto) {
entityManager.persist(produto);
}
}
public class ProdutoDao {
private EntityManager entityManager;
// recebe a dependência pronta
public ProdutoDao(EntityManager em) {
this.entityManager = em;
}
// usa a dependência
public void salvar(Produto produto) {
entityManager.persist(produto);
}
}
injeção de
dependências!
inversão de controle
injeção de
dependências!
separação de responsabilidades
inversão de controle
injeção de
dependências!
CDI
public class ProdutoDao {
private EntityManager entityManager;
public ProdutoDao(EntityManager em) {
this.entityManager = em;
}
public void salvar(Produto produto) {
entityManager.persist(produto);
}
}
public class ProdutoDao {
private EntityManager entityManager;
@Inject
public ProdutoDao(EntityManager em) {
this.entityManager = em;
}
public void salvar(Produto produto) {
entityManager.persist(produto);
}
}
public class ProdutoDao {
@Inject
private EntityManager entityManager;
public void salvar(Produto produto) {
entityManager.persist(produto);
}
}
@Inject
injeção de
dependências!
Injeção de dependências
por si só já é uma baita
diminuição de
acoplamento
Injeção de dependências
por si só já é uma baita
diminuição de
acoplamento
Mas, se pensar bem, ainda
estamos bem acoplados com a
dependência que recebemos
conexões
E se existirem JSPs que são
acessados diretamente e
abrem conexão com o banco?
conexões
Quando criar a conexão?
conexões
Podemos usar um filtro?
conexões
Lazy?
public static ConnectionContainer
putContainerInRequest(HttpServletRequest
request) {
ConnectionContainer container =
new ConnectionContainer();
request.setAttribute(ConnectionFactory.
OPEN_IN_VIEW_CONNECTION_CONTAINER,
container);
return container;
}
public static Connection
getConnectionFromRequest(HttpServletRequest
request) {
ConnectionContainer con =
(ConnectionContainer)request.getAttribute(
OPEN_IN_VIEW_CONNECTION_CONTAINER);
return con.getConnection();
}
ConnectionContainer {
private Connection connection;
public class
public Connection getConnection() {
if (connection == null) {
try {
connection =
ConnectionFactory.createNewConnection();
} catch (SQLException e) {
logError("Error blah", e);
}
}
return connection;
}
}
public Connection getCon(HttpServletRequest
request) throws SQLException {
return getConnectionFromRequest(request);
}
@RequestScoped
public Connection getCon(HttpServletRequest
request) throws SQLException {
return getConnectionFromRequest(request);
}
conexões
Podemos usar com
injeção?
@Produces
@RequestScoped
public Connection getCon(HttpServletRequest
request) throws SQLException {
return getConnectionFromRequest(request);
}
Utilizando esse mesmo
conceito no
EntityManaget
public class JPAUtil {
@Produces @ApplicationScoped
public EntityManagerFactory criaFactory() {
return
Persistence.createEntityManagerFactory("jpa");
}
@Produces @RequestScoped
public EntityManager
criaEM(EntityManagerFactory factory){
return factory.createEntityManager();
}
}
@produces
métodos
produtores!
login
<filter>
<init-param>
<param-name>restrictedUrl</param-name>
<param-value>
/sellerOrder.do, /buyerOrder.do,
/clientCategory.do, /clientCreate.do,
/clientEdit.do, /clientSearch.do,
/productCreate.do, ...
</param-value>
</init-param>
<init-param>
<param-name>restrictedCommands</param-name>
<param-value>
showUserPasswordForm, showOrderHistoryForm,
showUserFeedbackEditForm, showUserShopForm,
showUserBannerForm, showUserPictureForm,
showUserContactInfoForm, ...
</param-value>
</init-param>
</filter>
Dificuldade de
manutenção
@InterceptorBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface BlockUnloggedUsers { }
@InterceptorBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface BlockUnloggedUsers { }
@BlockUnloggedUsers
public class ProductSearchAction { /* ... */ }
@InterceptorBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface BlockUnloggedUsers { }
@BlockUnloggedUsers
public class ProductSearchAction { /* ... */ }
Bem Melhor!
Como testar ?
public class BlockedActionsTest {
private Class<?>[] blackListed =
new Class<?>[]{
BuyerOrderAction.class,
ClientCreateAction.class,
... };
@Test
public void shouldVerifyBlackListedActions(){
for (Class<?> blockedAction : blackListed){
assertNotNull(
blockedAction.getAnnotation(
BlockUnloggedUsers.class));
...
...
Method[] actionMethods =
blockedAction.getMethods();
for (Method method : actionMethods) {
assertNull(
method.getAnnotation(
UnloggedUsers.class));
}
}
@InterceptorBinding
interceptadores!
login
login
public void
loginIntoSession(LoginAuthentication
loginAuthentication, HttpServletRequest
request, HttpServletResponse response) {
UserInfo loginUser =
login.login(loginAuthentication);
SessionUtils.putIntoSession(request,loginUser);
SessionUtils.setLoggedUser(request, loginUser);
// + Código para merge dos carrinhos
// + Código de traqueamento
// = Código Monstro!
}
public void
loginIntoSession(LoginAuthentication
loginAuthentication, HttpServletRequest
request, HttpServletResponse response) {
UserInfo loginUser =
login.login(loginAuthentication);
SessionUtils.putIntoSession(request,loginUser);
SessionUtils.setLoggedUser(request, loginUser);
sessionLoginEvent.fire(
new SessionLogin(
loginUser, request, response));
}
@Inject
private Event<SessionLogin> sessionLoginEvent;
public void algumMetodoInteressado(
@Observers SessionLogin sessionLogin) {
// ...
}
@Observers
eventos!
Isso não é tudo!
decorators
stereotypes
injection points
custom scopes
conversation
scope
extensions
???
Qual framework adotar?
Como escolher?
JSF
Play!
Spring
VRaptor
???
Quão fácil é trocar um framework?
❏ Desenvolvedores não envolvidos
no processo?
Quão fácil é trocar um framework?
❏ Desenvolvedores não envolvidos
no processo?
❏ Entregas de produto?
Quão fácil é trocar um framework?
❏ Desenvolvedores não envolvidos
no processo?
❏ Entregas de produto?
❏ Ferias coletivas?
Neste caso trocar
é blocante!
Se já é difícil lidar com
um só, imagine dois!
Se já é difícil lidar com
um só, imagine dois!
if (analyser.isRouteToVRaptor((HttpServletRequest) req)) {
super.doFilter(req, res, chain);
} else {
Elo7MutableRequest mutableRequest =
new Elo7MutableRequest((HttpServletRequest) req);
Elo7MutableResponse mutableResponse =
new Elo7MutableResponse((HttpServletResponse) res);
StrutsRequestStarted request =
new StrutsRequestStarted(chain, mutableRequest,
mutableResponse);
strutsRequestStartedEvent.fire(request);
chain.doFilter(req, res);
}
Você deveria usar
CDI em todos os
seus projetos Java!
Considere usar
VRaptor em seus
projetos
Obrigado!
David Robert
@while42
Links adicionais
❏ Elo7
❏ Curso de Arquitetura Java
❏ Diminua suas dependências
com os eventos do CDI
❏ Porque você deveria usar CDI
nos seus projetos Java!
Download