SlideShare ist ein Scribd-Unternehmen logo
1 von 45
Downloaden Sie, um offline zu lesen
Spring @Aspect
e @Controller
Come utilizzare Spring
 AOP e Spring MVC per
scrivere migliori webapp
con meno codice e meno
         XML.




                 Massimiliano Dessì - desmax74@yahoo.it
                             Milano - 30/01/2009
Author
Java Architect   2008




Co-fondatore e consigliere

JugSardegna Onlus       2003




Fondatore e coordinatore:

SpringFramework Italian User Group                    2006




Jetspeed Italian User Group           2003




Groovy Italian User Group            2007




                        Massimiliano Dessì - desmax74@yahoo.it
                                    Milano - 30/01/2009
AOP



L' Aspect Oriented Programming supporta l'Object Oriented
Programming nella fase di implementazione, nei punti in cui
              mostra dei punti di debolezza.
L'AOP è complementare all' OOP nella fase implementativa.
            L' AOP deve essere utilizzato con
             giudizio e cognizione di causa.




                  Massimiliano Dessì - desmax74@yahoo.it
                              Milano - 30/01/2009
Limiti OOP

Code scattering, quando una funzionalità è implementata in
moduli diversi.
Si presenta in due forme:
- Blocchi di codice duplicato (es. identica implementazione di una
interfaccia in classi diverse)
- Blocchi di codice complementari della stessa funzionalità,

 posti in differenti moduli.
 (es in una ACL, un modulo esegue l'autenticazione e un altro
  l'autorizzazione)


                          Massimiliano Dessì - desmax74@yahoo.it
                                      Milano - 30/01/2009
Limiti OOP

    Code tangling, un modulo ha troppi compiti contemporanei.
public ModelAndView list(HttpServletRequest req, HttpServletResponse res)
    throws Exception {

    log(req);                                                   //logging

    if(req.isUserInRole("admin")){                              // authorization

        List users ;
        try {                                        //exception handling
    String username = req.getRemoteUser();
    users =cache.get(Integer.valueOf(conf.getValue("numberOfUsers")),
            username);                               //cache with authorization
    } catch (Exception e) {
        users = usersManager.getUsers();
    }

       return new ModelAndView("usersTemplate", "users", users);

    }else{
      return new ModelAndView("notAllowed");
    }
}
                           Massimiliano Dessì - desmax74@yahoo.it
                                       Milano - 30/01/2009
Conseguenze


-Evoluzione difficile, il codice è legato a diverse funzionalità
-Cattiva qualità, quale era la funzione del metodo ?
-Codice non riusabile, è adatto solo a questo scenario
-Tracciabilità, chi fa cosa ?
-Improduttività, dove è il punto dove intervenire ?

Eppure è scritto con un linguaggio Object Oriented...
L'implementazione è il vero problema, non il linguaggio.

                     Massimiliano Dessì - desmax74@yahoo.it
                                 Milano - 30/01/2009
Origine del problema

Le classi si ritrovano a dover implementare funzionalità trasversali.




Il problema non è più una classe che deve avere un solo
compito/scopo/responsabilità/funzionalità, ma come quel compito
viene richiamato per essere utilizzato.
                       Massimiliano Dessì - desmax74@yahoo.it
                                   Milano - 30/01/2009
AOP Solution

L' AOP fornisce i costrutti e gli strumenti per modularizzare
queste funzionalità che attraversano trasversalmente
l'applicazione (crosscutting concerns).
L' AOP permette quindi di centralizzare realmente il codice
duplicato consentendo di applicarlo secondo regole
prestabilite nei punti desiderati, durante il flusso di
esecuzione.



                    Massimiliano Dessì - desmax74@yahoo.it
                                Milano - 30/01/2009
AOP elements


Aspect: Corrisponde alla classe nell' OOP, contiene la
funzionalità trasversale (crosscutting concern).
Joinpoint: Punto di esecuzione del codice
(es l'invocazione di un costruttore, esecuzione di un metodo o
la gestione di una Exception)
Advice: L'azione da compiere nel joinpoint.
Pointcut: Contiene l'espressione che permette di individuare il
joinpoint al quale vogliamo applicare l'advice


                      Massimiliano Dessì - desmax74@yahoo.it
                                  Milano - 30/01/2009
AOP elements


Introduction: Permette l'aggiunta di interfacce e relativa
implementazione a runtime, a oggetti già definiti.
Target: Classe su cui agisce l'aspect con l'advice
Weaving: L'azione con cui vengono legati gli “attori” AOP e le
classi target.




                      Massimiliano Dessì - desmax74@yahoo.it
                                  Milano - 30/01/2009
AOP diagram

Come opera l' AOP




Massimiliano Dessì - desmax74@yahoo.it
            Milano - 30/01/2009
Spring AOP

Per permettere un utilizzo semplificato dell' AOP, Spring utilizza
come Joinpoint l'esecuzione dei metodi.
Questo significa che possiamo agire:
prima, dopo, attorno ad un metodo, alla sollevazione di una
eccezione, dopo l'esecuzione qualsiasi sia l' esito (finally),
utilizziamo normali classi Java con annotazioni oppure con XML.
Chi lavora nell' ombra per permetterci questa semplicità ?
          java.lang.reflect.Proxy oppure CGLIB



                       Massimiliano Dessì - desmax74@yahoo.it
                                   Milano - 30/01/2009
Spring AOP: take it easy

Dobbiamo solo preoccuparci di
decidere:

-Cosa centralizzare/modularizzare ?
-Quando deve entrare in azione ?

Cosa posso ottenere:

-Supporto al Domain Driven Design
-Meno codice
-Codice gestibile e manutenibile
-Meno scuse per usare realmente l'
OOP, non per spostare contenitori...

                       Massimiliano Dessì - desmax74@yahoo.it
                                   Milano - 30/01/2009
Spring AOP - Concorrenza

@Aspect() @Order(0)                                          Prima parte:
public class ConcurrentAspect {

 private final ReadWriteLock lock =                          -Mi creo dei lock rientranti in
   new ReentrantReadWriteLock();                             lettura e scrittura
 private final Lock rLock = lock.readLock();
 private final Lock wLock = lock.writeLock();
                                                             -Annoto la classe con
 @Pointcut("execution (* isAvailable(..))")
 private void isAvailable() {}
                                                             @Aspect

 @Pointcut("execution (* retainItem(..))")                   -Definisco con
 private void retainItem() {}
                                                             l'annotazione
 @Pointcut("execution (* release(..))")                      @Pointcut le espressioni
 private void release() {}
                                                             che mi indicano quando l'
 @Pointcut("release() || retainItem()")                      Aspect deve     intervenire.
 private void releaseOrRetain() {}




                          Massimiliano Dessì - desmax74@yahoo.it
                                      Milano - 30/01/2009
Spring AOP - Concorrenza

    @Before("isAvailable()")
                                               Seconda parte:
    public void setReadLock() {
        rLock.lock();                          Definisco riutilizzando i nomi
    }
                                               dei metodi sui quali ho
    @After("isAvailable()")                    annotato i @Pointcut la logica
    public void releaseReadLock() {
        rLock.unlock();
                                               da eseguire con i lock
    }
                                               Con le annotazioni seguenti
    @Before("releaseOrRetain()")
    public void setWriteLock() {               dichiaro quando voglio sia
        wLock.lock();                          eseguita
    }

    @After("releaseOrRetain()")                @Before
    public void releaseWriteLock() {           @After
        wLock.unlock();
    }
                                               @AfterReturning
}                                              @Around
                                               @AfterThrowing

                          Massimiliano Dessì - desmax74@yahoo.it
                                      Milano - 30/01/2009
Spring AOP – Advice Type

                  Gli advice non solo ci permettono di eseguire logica
                  nei punti definti dai pointcut, ma anche di ottenere
@Before
                  informazioni sulla esecuzione (classe target, metodo
@After            chiamato, argomenti passati, valore restituito)
                  Con alcuni tipi di advice (around) anche di avere il
@AfterReturning   controllo sul flusso di esecuzione.
                  La classe chiamante naturalmente non sa nulla di
@Around           quello che avviene, vede sempre una semplice
                  classe ....
@AfterThrowing




                   Massimiliano Dessì - desmax74@yahoo.it
                               Milano - 30/01/2009
Spring AOP – Pointcut

•   execution     Nei pointcut precedenti abbiamo visto come espressione
•   within        per definire il punto di applicazione fosse l' esecuzione di
•   this          un metodo con un determinato nome.

•   target        Abbiamo a disposizione anche altri designatori di
                  pointcut per avere il massimo controllo.
•   args
•   @target
•   @args
•   @within
•   @annotation
●   bean

                       Massimiliano Dessì - desmax74@yahoo.it
                                   Milano - 30/01/2009
Spring AOP – JMX

@ManagedResource("freshfruitstore:type=TimeExecutionManagedAspect")
@Aspect() @Order(2)
public class TimeExecutionManagedAspect {

  @ManagedAttribute                                                Oltre a poter intervenire nel
  public long getAverageCallTime() {
    return (this.callCount > 0                                     flusso di escuzione, posso
     ? this.accumulatedCallTime / this.callCount : 0);
  }
                                                                   anche gestire gli Aspect
  @ManagedOperation
  public void resetCounters() {                                    stessi con JMX,
     this.callCount = 0;

  }
     this.accumulatedCallTime = 0;
                                                                   esponendo come attributi o
  @ManagedAttribute                                                operazioni, i normali
  public long getAverageCallTime() {
    return (this.callCount > 0 ?                                   metodi dell' Aspect che è
     this.accumulatedCallTime / this.callCount : 0);
  }
                                                                   sempre una classe java.
    ...




                              Massimiliano Dessì - desmax74@yahoo.it
                                          Milano - 30/01/2009
Spring AOP – JMX
...

@Around("within(it.mypackage.service.*Impl)")                            Posso quindi con JMX
public Object invoke(ProceedingJoinPoint joinPoint)
    throws Throwable {
                                                                         cambiare il
      if (this.isTimeExecutionEnabled) {
         StopWatch sw = new StopWatch(joinPoint.toString());       comportamento
         sw.start("invoke");
         try {                                                     dell' Aspect a runtime
             return joinPoint.proceed();
         } finally {
             sw.stop();
             synchronized (this) {
                this.accumulatedCallTime += sw.getTotalTimeMillis();
             }
                logger.info(sw.prettyPrint());
             }
         } else {
             return joinPoint.proceed();
         }
       }
...




                                Massimiliano Dessì - desmax74@yahoo.it
                                            Milano - 30/01/2009
...
                            Spring AOP – Introductions

Una introduction mi permette di decorare un
oggetto a runtime, aggiungendogli interfacce e
relativa implementazione.
Questo permette sia di evitare la duplicazione
di una implementazione, sia di simulare l'
ereditarietà multipla che java non ha.
  @Aspect
  public class ParallelepipedIntroduction {

      @DeclareParents(value = "org.springaop.chapter.four.introduction.Box",
          defaultImpl = Titanium.class)
      public Matter matter;

      @DeclareParents(value = "org.springaop.chapter.four.introduction.Box",
          defaultImpl = Cube.class)
      public GeometricForm geometricForm;
  }


                               Massimiliano Dessì - desmax74@yahoo.it
                                           Milano - 30/01/2009
...
                                        Spring AOP – @Aspect

  Le annotazioni viste finora compresa la sintassi dei pointcut sono fornite da
  AspectJ

  import org.aspectj.lang.annotation.*

  ma sono assolutamente dentro il “contesto” di Spring e su dei bean di
  Spring.
  Vediamo ora invece cosa possiamo utilizzare di Spring (IoC) fuori dal
  “contesto” di Spring tramite AspectJ.
  Dovremo scendere a qualche compromesso...



                           Massimiliano Dessì - desmax74@yahoo.it
                                       Milano - 30/01/2009
DDD

                         Aggregates                      Domain-Driven Design è un modo
  Entities
                                                         di pensare le applicazioni.
               Modules                Factories          Suggerendo di concentrare
                                                         l'attenzione sul dominio del
Services
                               Repositories              problema, invitando a ragionare ad
             Value Objects                               oggetti e non in base a contenitori
                                                         di dati da movimentare...
Application Layer            Infrastructure Layer



                                 UI Layer
      Domain Layer



                                Massimiliano Dessì - desmax74@yahoo.it
                                            Milano - 30/01/2009
DDD

                                                                               Nelle entità è concentrata
public interface Customer extends NamedEntity {
                                                                               la logica di business, non
    public Address getAddress();

    public ContactInformation getContact();                                    nei servizi che eseguono
    public void modifyContactInformation(ContactInformation contact);
                                                                               “procedure”...
    public void modifyAddress(Address address);

    public Boolean saveCustomer();
                                                                               In questo modo i nostri
    public Boolean createOrder();                                              oggetti hanno dati e
    public Boolean saveOrder();
                                                                               comportamenti, come
    public Order getOrder();

    public List<Order> getOrders();                                            dovrebbe essere nelle
}
                                                                               classi ad oggetti




                                      Massimiliano Dessì - desmax74@yahoo.it
                                                  Milano - 30/01/2009
SpringAOP +DDD +AspectJ
@Configurable(dependencyCheck = true, autowire=Autowire.BY_TYPE)
public class CustomerImpl implements Customer, Serializable {

      @Autowired
      public void setCustomerRepository(@Qualifier("customerRepository") CustomerRepository customerRepo) {
           this.customerRepository = customerRepository;
      }

      @Autowired
      public void setOrderRepository(@Qualifier("orderRepository") OrderRepository orderRepo) {
           this.orderRepository = orderRepo;
      }


      public Boolean createOrder() {
           Boolean result = false;
           if (order == null) {
                order = new OrderImpl.Builder(Constants.ID_NEW, new Date(), id
                          .toString()).build();
                result = true;
           }
           return result;
      }

      public Boolean saveCustomer() {
           return customerRepository.saveCustomer(this);
      }

...



                                     Massimiliano Dessì - desmax74@yahoo.it
                                                 Milano - 30/01/2009
SpringAOP +AspectJ

Con @Configurable abbiamo dichiarando che alla classe verranno iniettate
delle dipendenze benchè non sia uno spring bean.
L' applicationContext di Spring conosce la classe semplicemente come un
bean prototype.
Per avere questa funzionalità abbiamo necessità di comunicare alla jvm il jar
di spring da usare per il Load Time Weaving:
-javaagent:<path>spring-agent.jar

oppure configurare tomcat in questo modo per farlo al nostro posto:
<Loader
loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"
     useSystemClassLoaderAsParent="false"/>




                                Massimiliano Dessì - desmax74@yahoo.it
                                            Milano - 30/01/2009
Spring AOP +AspectJ Weaver

Utilizzare l'AspectJ Weaver comporta un approccio diverso rispetto alla
semplicità di SpringAOP vista sinora.
Annotare delle classi come @Aspect e farli creare da Spring, significa
rimanere comunque dentro l' IoC Container, così come definire pointcut su
esecuzioni di metodi da parte di bean di Spring.
Con il LTW stiamo dicendo a Spring di operare fuori dal suo “contesto”, per
iniettare le dipendenze su oggetti non creati dall' IoC.
Per utilizzare il LTW definiamo su un file per AspectJ le classi su cui deve
operare e quali Aspect deve creare, Aspects che non sono bean creati da
Spring...


                          Massimiliano Dessì - desmax74@yahoo.it
                                      Milano - 30/01/2009
LTW - aop.xml

100% AspectJ

<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN"
"http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver options="-showWeaveInfo
-XmessageHandlerClass:org.springframework.aop.aspectj.AspectJWeaverMessageHandler">
     <!-- only weave classes in our application-specific packages -->
     <include within="it.freshfruits.domain.entity.*"/>
     <include within="it.freshfruits.domain.factory.*"/>
     <include within="it.freshfruits.domain.service.*"/>
     <include within="it.freshfruits.domain.vo.*"/>
     <include within="it.freshfruits.application.repository.*"/>
     <exclude within="it.freshfruits.aspect.*"/>
</weaver>
<aspects>
        <aspect name="it.freshfruits.aspect.ConcurrentAspect" />
        <aspect name="it.freshfruits.aspect.LogManagedAspect" />
        <aspect name="it.freshfruits.aspect.TimeExecutionManagedAspect" />
</aspects>
</aspectj>




                                  Massimiliano Dessì - desmax74@yahoo.it
                                              Milano - 30/01/2009
Spring AOP +AspectJ Weaver

Una volta che abbiamo le dipendenze in una entità del dominio,
sia con l'iniezione delle dipendenze con il LTW, o tramite passaggio delle
dipendenze come argomenti del costruttore ad opera di una factory,
vediamo il risultato sulla UI.




                          Massimiliano Dessì - desmax74@yahoo.it
                                      Milano - 30/01/2009
DDD UI
@Controller("customerController")
public class CustomerController {

      @RequestMapping("/customer.create.page")
      public ModelAndView create(HttpServletRequest req) {
        return new ModelAndView("customer/create", "result", UiUtils.getCustomer(req).createOrder());
      }

      @RequestMapping("/customer.order.page")
      public ModelAndView order(HttpServletRequest req) {
        return new ModelAndView("customer/order", "order", UiUtils.getOrder(req));
      }

      @RequestMapping("/customer.items.page")
      public ModelAndView items(HttpServletRequest req) {
        return new ModelAndView("customer/items", "items", UiUtils.getOrder(req).getOrderItems());
      }
...
}

I controller risultanti saranno completamente stateless e senza dipendenze, e
con una semplice chiamata sulla entità.


                                       Massimiliano Dessì - desmax74@yahoo.it
                                                   Milano - 30/01/2009
DDD UI

Handler Interceptor che pone nella HttpServletRequest l'entità customer
utilizzata dal Customer Controller

public class CustomerInterceptor extends HandlerInterceptorAdapter {

  @Override
  public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) throws
Exception {
    req.setAttribute(Constants.CUSTOMER, customerFactory.getCurrentCustomer());
    return true;
  }

    @Autowired
    private CustomerFactory customerFactory;
}




                                   Massimiliano Dessì - desmax74@yahoo.it
                                               Milano - 30/01/2009
Benefici



OOP + AOP + DDD
        =
 Codice a oggetti
  Codice pulito
 Codice elegante




           Massimiliano Dessì - desmax74@yahoo.it
                       Milano - 30/01/2009
Spring MVC
                                                                                 Handler Mapping
                                                                 2




Request     1                                                3
                                                                                   Controller
                Dispatcher Servlet                 ModelAndView
 Response                                                                    4



                                                                         5
                                                                                 ViewResolver


                                                                     6

                                                                                    View



                              Massimiliano Dessì - desmax74@yahoo.it
                                          Milano - 30/01/2009
Form Controller
@Controller("fruitController") @RequestMapping("/fruit.edit.admin")
public class FruitController {

    @RequestMapping(method = RequestMethod.POST)
    public String processSubmit(@ModelAttribute("fruit") FruitMap fruit, BindingResult result,
               SessionStatus status) {

        validator.validate(fruit, result);
        if (result.hasErrors()) {
            return "userForm";
        } else {
            fruit.save();
            status.setComplete();
            return "redirect:role.list.admin";
        }
    }

    @InitBinder()
    public void initBinder(WebDataBinder binder) throws Exception {
        binder.registerCustomEditor(String.class, new StringTrimmerEditor(false));
    }

    @RequestMapping(method = RequestMethod.GET)
    public String setupForm(@RequestParam(required = false, value = "id") Integer id, ModelMap model) {
        model.addAttribute(Constants.FRUIT, id == null ? new FruitMap() : fruitRepository.getFruitType(id));
        return "role/form";
    }

    @Autowired @Qualifier("fruitRepository")
    private FruitTypeRepository fruitRepository;
    @Autowired @Qualifier("fruitValidator")
    FruitValidator validator;
}


                                    Massimiliano Dessì - desmax74@yahoo.it
                                                Milano - 30/01/2009
MultiAction Controller
@Controller("customerController")
public class CustomerController {

    @RequestMapping("/customer.create.page")
    public ModelAndView create(HttpServletRequest req) {
        return new ModelAndView("customer/create", "result", UiUtils.getCustomer(req).createOrder());
    }

    @RequestMapping("/customer.save.page")
    public ModelAndView save(HttpServletRequest req) {
        return new ModelAndView("customer/save", "result", UiUtils.getCustomer(req).saveOrder());
    }

    @RequestMapping("/customer.show.page")
    public ModelAndView show(HttpServletRequest req) {
        return new ModelAndView("customer/show", "customer", UiUtils.getCustomer(req));
    }

    @RequestMapping("/customer.order.page")
    public ModelAndView order(HttpServletRequest req) {
        return new ModelAndView("customer/order", "order", UiUtils.getOrder(req));
    }

    @RequestMapping("/customer.items.page")
    public ModelAndView items(HttpServletRequest req) {
        return new ModelAndView("customer/items", "items", UiUtils.getOrder(req).getOrderItems());
    }

    @RequestMapping("/customer.remove.page")
    public ModelAndView remove(@RequestParam("id") String id, HttpServletRequest req) throws Exception {
        Order order = UiUtils.getOrder(req);
        return order.removeOrderItem(order.getId().toString(), id) ? new ModelAndView("customer/items",
           "items", order.getOrderItems()) : new ModelAndView("customer/remove", "result", false);
    }
}

                                    Massimiliano Dessì - desmax74@yahoo.it
                                                Milano - 30/01/2009
Configuration

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">

<context:component-scan base-package="it.freshfruits.ui"/>
<context:annotation-config/>

<bean name="urlMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
     <property name="interceptors">
           <list>
                <ref bean="customerInterceptor"/>
            </list>
      </property>
</bean>

<bean name="customerInterceptor" class="it.freshfruits.ui.interceptor.CustomerInterceptor"/>

</beans>




                                   Massimiliano Dessì - desmax74@yahoo.it
                                               Milano - 30/01/2009
Spring Security
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.4.xsd">

       <sec:http>
              <sec:intercept-url pattern="/log*.jsp" filters="none" />
              <sec:intercept-url pattern="/*.page" access="ROLE_USER" />
              <sec:intercept-url pattern="/*.admin" access="ROLE_ADMIN" />
              <sec:form-login login-page="/login.jsp" default-target-url="/" login-processing-url="/j_security_check"
                     authentication-failure-url="/loginError.jsp" />
              <sec:logout logout-url="/logout.jsp" invalidate-session="true" logout-success-url="/login.jsp" />
              <sec:remember-me />
              <sec:intercept-url pattern="*.htm" access="ROLE_USER,ROLE_ANONYMOUS" />
              <sec:intercept-url pattern="*.page" access="ROLE_USER,ROLE_ADMIN" />
              <sec:intercept-url pattern="*.edit" access="ROLE_USER,ROLE_ADMIN" />
              <sec:intercept-url pattern="*.admin" access="ROLE_ADMIN" />
       </sec:http>

       <sec:authentication-provider user-service-ref="sffsUserDetailservice"><sec:password-encoder hash="sha" /></sec:authentication-provider>

       <bean id="accessDecisionManager" class="org.springframework.security.vote.AffirmativeBased">
               <property name="decisionVoters">
                      <list>
                              <bean class="org.springframework.security.vote.RoleVoter" />
                              <bean class="org.springframework.security.vote.AuthenticatedVoter" />
                      </list>
               </property>
       </bean>

       <bean id="sffsUserDetailservice" class="it.freshfruits.security.AuthenticationJdbcDaoImpl"
              p:rolePrefix="ROLE_" p:dataSource-ref="dataSource"
              p:usersByUsernameQuery="SELECT username, password, enabled FROM authentication WHERE username = ?"
              p:authoritiesByUsernameQuery="SELECT username, authority FROM roles WHERE username = ?" />

       <sec:global-method-security access-decision-manager-ref="accessDecisionManager">
               <sec:protect-pointcut expression="execution(* it.freshfruits.domain.entity.*.*(..))"
                      access="ROLE_USER,ROLE_ADMIN" />
       </sec:global-method-security>
...

</beans>


                                                    Massimiliano Dessì - desmax74@yahoo.it
                                                                Milano - 30/01/2009
WEB.XML
...
<context-param>
     <param-name>webAppRootKey</param-name>
     <param-value>springFreshFruitsStore.root</param-value>
</context-param>
<context-param>
     <param-name>contextConfigLocation</param-name>
     <param-value>/WEB-INF/conf/spring/sffs-*.xml</param-value>
</context-param>
<listener>
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
     <filter-name>springSecurityFilterChain</filter-name>
     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<servlet>
     <servlet-name>sffs</servlet-name>
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
     <load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping><servlet-name>sffs</servlet-name><url-pattern>*.page</url-pattern></servlet-mapping>
<servlet-mapping><servlet-name>sffs</servlet-name><url-pattern>*.edit</url-pattern></servlet-mapping>
<servlet-mapping><servlet-name>sffs</servlet-name><url-pattern>*.admin</url-pattern></servlet-mapping>
<servlet-mapping><servlet-name>sffs</servlet-name><url-pattern>*.htm</url-pattern></servlet-mapping>
...




                                   Massimiliano Dessì - desmax74@yahoo.it
                                               Milano - 30/01/2009
Jsp paginated list
<%@ include file="/WEB-INF/jsp/taglibs.jsp"%>
<tag:pager href="user.list.page"/>
<div>
    <div align="center"><span><spring:message code="ui.users"/></span></div>
    <c:if test="${msg ne ''}">${msg}</c:if>
    <table class="list">
        <thead><tr><th align="left"><spring:message code="ui.user.username"/></th></tr></thead>
        <tbody>
        <c:forEach var="user" items="${users}" varStatus="status">
             <c:choose>
             <c:when test="${status.count % 2 == 0}">
             <tr class="table-row-dispari"></c:when>
             <c:otherwise>
             <tr class="table-row-pari"></c:otherwise>
             </c:choose>
                 <td align="left">${user.username}</td>
                 <td align="center">
                   <a href="user.roles.page?sid=${user.id}"><img border="0" title="<spring:message code="ui.action.view"/>"
                   alt="<spring:message code="ui.action.view"/>" src="img/view.png"/></a>
                 </td>
                 <td align="center">
                   <a href="user.detail.page?sid=${user.id}"><img border="0" title="<spring:message code="ui.action.edit"/>"
                   alt="<spring:message code="ui.action.edit"/>" src="img/edit.png"/></a></td>
             </tr>
        </c:forEach>
        </tbody>
    </table>
</div>
<br/>
<tag:pager href="user.list.page"/>
<div align="center">
<input type="image" src="img/add.png" title="<spring:message code="ui.action.user.new"/>" alt="<spring:message
code="ui.action.user.new"/>" onclick="location.href = 'user.edit.page'" value="<spring:message code="ui.action.user.new"/>"/>
</div>



                                          Massimiliano Dessì - desmax74@yahoo.it
                                                      Milano - 30/01/2009
Spring MVC Portlet
                                                                                 Portlet
Deja vu ?                                                                    Handler Mapping
                                                             2




      1                                                  3
                                                                                Controller
            Dispatcher Portlet                 ModelAndView
                                                                         4



                                                                     5
                                                                             ViewResolver


                                                                 6
                                                                             ViewRenderer
                                                                                Servlet


                          Massimiliano Dessì - desmax74@yahoo.it
                                      Milano - 30/01/2009
Spring riutilizza gli stessi concetti della parte MVC Servlet,
traslando dove serve le richieste Portlet (action o render) in Servlet,
permettendo il riuso dei controller.
Spring fornisce una NativeWebRequest che maschera il tipo di
richiesta, questo approccio ci permette di scrivere controller che
virtualmente possono non sapere dentro cosa stanno girando.
In pratica, i problemi li può creare il portal server...
Nonostante i problemi con il portal server, è comunque possibile
riutilizzare la gran parte del codice scritto per una webapp normale.




                           Massimiliano Dessì - desmax74@yahoo.it
                                       Milano - 30/01/2009
Massimiliano Dessì - desmax74@yahoo.it
            Milano - 30/01/2009
Se abbiamo
disegnato bene la
nostra webapp
con SpringMVC,
non è troppo
complesso
portarlo su
SpringMVC Portlet




                    Massimiliano Dessì - desmax74@yahoo.it
                                Milano - 30/01/2009
Spring AOP Book

                                  Maggiori
                                informazioni
                               a febbraio su :

                            http://www.packtpub.com




                        Un enorme grazie a Stefano Sanna per il
                       supporto durante la scrittura del libro. Se è
                        stato terminato è grazie al suo contributo
                                 che non è mai mancato.


Massimiliano Dessì - desmax74@yahoo.it
            Milano - 30/01/2009
Domande ?




      Massimiliano Dessì - desmax74@yahoo.it
                  Milano - 30/01/2009
Grazie per l'attenzione !

           Massimiliano Dessì
           desmax74 at yahoo.it
                      http://jroller.com/desmax
               http://www.linkedin.com/in/desmax74
      http://wiki.java.net/bin/view/People/MassimilianoDessi
 http://www.jugsardegna.org/vqwiki/jsp/Wiki?MassimilianoDessi



               Spring Framework Italian User Group
     http://it.groups.yahoo.com/group/SpringFramework-it




         Massimiliano Dessì - desmax74@yahoo.it
                     Milano - 30/01/2009

Weitere ähnliche Inhalte

Was ist angesagt?

Progetto SOD Davide Sito
Progetto SOD Davide SitoProgetto SOD Davide Sito
Progetto SOD Davide Sito
Davide Sito
 

Was ist angesagt? (20)

Progetto SOD Davide Sito
Progetto SOD Davide SitoProgetto SOD Davide Sito
Progetto SOD Davide Sito
 
OSGi e Liferay 7
OSGi e Liferay 7OSGi e Liferay 7
OSGi e Liferay 7
 
Mvc e di spring e angular js
Mvc e di   spring e angular jsMvc e di   spring e angular js
Mvc e di spring e angular js
 
Introduzione agli Hooks – Primo Episodio
Introduzione agli Hooks – Primo EpisodioIntroduzione agli Hooks – Primo Episodio
Introduzione agli Hooks – Primo Episodio
 
Introduzione a Struts
Introduzione a StrutsIntroduzione a Struts
Introduzione a Struts
 
Acadevmy - Angular Overview
Acadevmy - Angular OverviewAcadevmy - Angular Overview
Acadevmy - Angular Overview
 
Corso introduttivo di Design Pattern in Java per Elis - 1
Corso introduttivo di Design Pattern in Java per Elis - 1Corso introduttivo di Design Pattern in Java per Elis - 1
Corso introduttivo di Design Pattern in Java per Elis - 1
 
Microservices
MicroservicesMicroservices
Microservices
 
Real Spring Aop Recipes For Your Everyday Job
Real Spring Aop Recipes For Your Everyday JobReal Spring Aop Recipes For Your Everyday Job
Real Spring Aop Recipes For Your Everyday Job
 
MVC and Struts 1
MVC and Struts 1MVC and Struts 1
MVC and Struts 1
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
Liferay 7: Come realizzare un client SOAP con Apache CXF in OSGi Style
Liferay 7: Come realizzare un client SOAP con Apache CXF in OSGi StyleLiferay 7: Come realizzare un client SOAP con Apache CXF in OSGi Style
Liferay 7: Come realizzare un client SOAP con Apache CXF in OSGi Style
 
Java EE facile con Spring Boot - Luigi Bennardis - Codemotion Roma 2015
Java EE facile con Spring Boot - Luigi Bennardis - Codemotion Roma 2015Java EE facile con Spring Boot - Luigi Bennardis - Codemotion Roma 2015
Java EE facile con Spring Boot - Luigi Bennardis - Codemotion Roma 2015
 
Introduzione ad angular 7/8
Introduzione ad angular 7/8Introduzione ad angular 7/8
Introduzione ad angular 7/8
 
Struttin' on, novità in casa Struts
Struttin' on, novità in casa StrutsStruttin' on, novità in casa Struts
Struttin' on, novità in casa Struts
 
Non solo Django: MVC orientato agli oggetti con Plone e Zope Toolkit
Non solo Django: MVC orientato agli oggetti con Plone e Zope ToolkitNon solo Django: MVC orientato agli oggetti con Plone e Zope Toolkit
Non solo Django: MVC orientato agli oggetti con Plone e Zope Toolkit
 
Liferay: Esporre Web Services Custom
Liferay: Esporre Web Services CustomLiferay: Esporre Web Services Custom
Liferay: Esporre Web Services Custom
 
Tutte le novità di ASP.NET MVC3
Tutte le novità di ASP.NET MVC3Tutte le novità di ASP.NET MVC3
Tutte le novità di ASP.NET MVC3
 
JAX-WS e JAX-RS
JAX-WS e JAX-RSJAX-WS e JAX-RS
JAX-WS e JAX-RS
 
Corso Javascript
Corso JavascriptCorso Javascript
Corso Javascript
 

Ähnlich wie Spring @Aspect e @Controller

Aspect Oriented Programming
Aspect Oriented ProgrammingAspect Oriented Programming
Aspect Oriented Programming
Andrea Bozzoni
 
Design pattern template method
Design pattern template methodDesign pattern template method
Design pattern template method
Nelson Firmani
 
Implementazione di una Web App per la verifica dei requisiti progettuali del ...
Implementazione di una Web App per la verifica dei requisiti progettuali del ...Implementazione di una Web App per la verifica dei requisiti progettuali del ...
Implementazione di una Web App per la verifica dei requisiti progettuali del ...
Luca Dalle Vedove
 
Lezione design patterns 2011 (Peron)
Lezione design patterns 2011 (Peron)Lezione design patterns 2011 (Peron)
Lezione design patterns 2011 (Peron)
lukebonham
 

Ähnlich wie Spring @Aspect e @Controller (20)

Aspect Oriented Programming
Aspect Oriented ProgrammingAspect Oriented Programming
Aspect Oriented Programming
 
[Objective-C] - Introduzione
[Objective-C] - Introduzione[Objective-C] - Introduzione
[Objective-C] - Introduzione
 
AreaMVC: un'architettura software basata sulla semplicità
AreaMVC: un'architettura software basata sulla semplicitàAreaMVC: un'architettura software basata sulla semplicità
AreaMVC: un'architettura software basata sulla semplicità
 
PowerMock TDD User Group Milano
PowerMock TDD User Group MilanoPowerMock TDD User Group Milano
PowerMock TDD User Group Milano
 
Organizza il lavoro
Organizza il lavoroOrganizza il lavoro
Organizza il lavoro
 
Drupal Day 2011 - Organizza il tuo lavoro
Drupal Day 2011 - Organizza il tuo lavoroDrupal Day 2011 - Organizza il tuo lavoro
Drupal Day 2011 - Organizza il tuo lavoro
 
Design pattern template method
Design pattern template methodDesign pattern template method
Design pattern template method
 
Corso Java
Corso JavaCorso Java
Corso Java
 
Implementazione di una Web App per la verifica dei requisiti progettuali del ...
Implementazione di una Web App per la verifica dei requisiti progettuali del ...Implementazione di una Web App per la verifica dei requisiti progettuali del ...
Implementazione di una Web App per la verifica dei requisiti progettuali del ...
 
L'avventura dell'interprete UI - Un'indagine Java di Lotus Holmes
L'avventura dell'interprete UI - Un'indagine Java di Lotus HolmesL'avventura dell'interprete UI - Un'indagine Java di Lotus Holmes
L'avventura dell'interprete UI - Un'indagine Java di Lotus Holmes
 
Sviluppo Rapido Di Applicazioni Con Grails
Sviluppo Rapido Di Applicazioni Con GrailsSviluppo Rapido Di Applicazioni Con Grails
Sviluppo Rapido Di Applicazioni Con Grails
 
Dessi Tech Day2008 Cagliari
Dessi Tech Day2008 CagliariDessi Tech Day2008 Cagliari
Dessi Tech Day2008 Cagliari
 
Corso Unified Modeling Language (UML)
Corso Unified Modeling Language (UML)Corso Unified Modeling Language (UML)
Corso Unified Modeling Language (UML)
 
Yii Framework - yes it is rapid web application development (Parte 1)
Yii Framework - yes it is rapid web application development (Parte 1)Yii Framework - yes it is rapid web application development (Parte 1)
Yii Framework - yes it is rapid web application development (Parte 1)
 
Java Symbolic Regression - Machine Learining
Java Symbolic Regression - Machine LeariningJava Symbolic Regression - Machine Learining
Java Symbolic Regression - Machine Learining
 
Mashlight
MashlightMashlight
Mashlight
 
Lezione design patterns 2011 (Peron)
Lezione design patterns 2011 (Peron)Lezione design patterns 2011 (Peron)
Lezione design patterns 2011 (Peron)
 
Generazione di diagrammi ArchiMate da modelli ontologici di EA e meta modello...
Generazione di diagrammi ArchiMate da modelli ontologici di EA e meta modello...Generazione di diagrammi ArchiMate da modelli ontologici di EA e meta modello...
Generazione di diagrammi ArchiMate da modelli ontologici di EA e meta modello...
 
Xcode - Just do it
Xcode - Just do itXcode - Just do it
Xcode - Just do it
 
Machine learning models continuous deployment on azure using devops
Machine learning models continuous deployment on azure using devopsMachine learning models continuous deployment on azure using devops
Machine learning models continuous deployment on azure using devops
 

Mehr von Massimiliano Dessì

Mehr von Massimiliano Dessì (20)

Code One 2018 maven
Code One 2018   mavenCode One 2018   maven
Code One 2018 maven
 
When Old Meets New: Turning Maven into a High Scalable, Resource Efficient, C...
When Old Meets New: Turning Maven into a High Scalable, Resource Efficient, C...When Old Meets New: Turning Maven into a High Scalable, Resource Efficient, C...
When Old Meets New: Turning Maven into a High Scalable, Resource Efficient, C...
 
Hacking Maven Linux day 2017
Hacking Maven Linux day 2017Hacking Maven Linux day 2017
Hacking Maven Linux day 2017
 
Microservices in Go_Dessi_Massimiliano_Codemotion_2017_Rome
Microservices in Go_Dessi_Massimiliano_Codemotion_2017_Rome Microservices in Go_Dessi_Massimiliano_Codemotion_2017_Rome
Microservices in Go_Dessi_Massimiliano_Codemotion_2017_Rome
 
Dessi docker kubernetes paas cloud
Dessi docker kubernetes paas cloudDessi docker kubernetes paas cloud
Dessi docker kubernetes paas cloud
 
Docker dDessi november 2015
Docker dDessi november 2015Docker dDessi november 2015
Docker dDessi november 2015
 
Docker linuxday 2015
Docker linuxday 2015Docker linuxday 2015
Docker linuxday 2015
 
Openshift linuxday 2014
Openshift linuxday 2014Openshift linuxday 2014
Openshift linuxday 2014
 
Web Marketing Training 2014 Community Online
Web Marketing Training 2014 Community OnlineWeb Marketing Training 2014 Community Online
Web Marketing Training 2014 Community Online
 
Vert.X like Node.js but polyglot and reactive on JVM
Vert.X like Node.js but polyglot and reactive on JVMVert.X like Node.js but polyglot and reactive on JVM
Vert.X like Node.js but polyglot and reactive on JVM
 
Reactive applications Linux Day 2013
Reactive applications Linux Day 2013Reactive applications Linux Day 2013
Reactive applications Linux Day 2013
 
Scala Italy 2013 extended Scalatra vs Spring MVC
Scala Italy 2013 extended Scalatra vs Spring MVCScala Italy 2013 extended Scalatra vs Spring MVC
Scala Italy 2013 extended Scalatra vs Spring MVC
 
Codemotion 2013 scalatra_play_spray
Codemotion 2013 scalatra_play_sprayCodemotion 2013 scalatra_play_spray
Codemotion 2013 scalatra_play_spray
 
Why we cannot ignore functional programming
Why we cannot ignore functional programmingWhy we cannot ignore functional programming
Why we cannot ignore functional programming
 
Scala linux day 2012
Scala linux day 2012 Scala linux day 2012
Scala linux day 2012
 
Three languages in thirty minutes
Three languages in thirty minutesThree languages in thirty minutes
Three languages in thirty minutes
 
MongoDB dessi-codemotion
MongoDB dessi-codemotionMongoDB dessi-codemotion
MongoDB dessi-codemotion
 
MongoDB Webtech conference 2010
MongoDB Webtech conference 2010MongoDB Webtech conference 2010
MongoDB Webtech conference 2010
 
RESTEasy
RESTEasyRESTEasy
RESTEasy
 
Spring Roo Internals Javaday IV
Spring Roo Internals Javaday IVSpring Roo Internals Javaday IV
Spring Roo Internals Javaday IV
 

Spring @Aspect e @Controller

  • 1. Spring @Aspect e @Controller Come utilizzare Spring AOP e Spring MVC per scrivere migliori webapp con meno codice e meno XML. Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 2. Author Java Architect 2008 Co-fondatore e consigliere JugSardegna Onlus 2003 Fondatore e coordinatore: SpringFramework Italian User Group 2006 Jetspeed Italian User Group 2003 Groovy Italian User Group 2007 Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 3. AOP L' Aspect Oriented Programming supporta l'Object Oriented Programming nella fase di implementazione, nei punti in cui mostra dei punti di debolezza. L'AOP è complementare all' OOP nella fase implementativa. L' AOP deve essere utilizzato con giudizio e cognizione di causa. Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 4. Limiti OOP Code scattering, quando una funzionalità è implementata in moduli diversi. Si presenta in due forme: - Blocchi di codice duplicato (es. identica implementazione di una interfaccia in classi diverse) - Blocchi di codice complementari della stessa funzionalità, posti in differenti moduli. (es in una ACL, un modulo esegue l'autenticazione e un altro l'autorizzazione) Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 5. Limiti OOP Code tangling, un modulo ha troppi compiti contemporanei. public ModelAndView list(HttpServletRequest req, HttpServletResponse res) throws Exception { log(req); //logging if(req.isUserInRole("admin")){ // authorization List users ; try { //exception handling String username = req.getRemoteUser(); users =cache.get(Integer.valueOf(conf.getValue("numberOfUsers")), username); //cache with authorization } catch (Exception e) { users = usersManager.getUsers(); } return new ModelAndView("usersTemplate", "users", users); }else{ return new ModelAndView("notAllowed"); } } Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 6. Conseguenze -Evoluzione difficile, il codice è legato a diverse funzionalità -Cattiva qualità, quale era la funzione del metodo ? -Codice non riusabile, è adatto solo a questo scenario -Tracciabilità, chi fa cosa ? -Improduttività, dove è il punto dove intervenire ? Eppure è scritto con un linguaggio Object Oriented... L'implementazione è il vero problema, non il linguaggio. Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 7. Origine del problema Le classi si ritrovano a dover implementare funzionalità trasversali. Il problema non è più una classe che deve avere un solo compito/scopo/responsabilità/funzionalità, ma come quel compito viene richiamato per essere utilizzato. Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 8. AOP Solution L' AOP fornisce i costrutti e gli strumenti per modularizzare queste funzionalità che attraversano trasversalmente l'applicazione (crosscutting concerns). L' AOP permette quindi di centralizzare realmente il codice duplicato consentendo di applicarlo secondo regole prestabilite nei punti desiderati, durante il flusso di esecuzione. Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 9. AOP elements Aspect: Corrisponde alla classe nell' OOP, contiene la funzionalità trasversale (crosscutting concern). Joinpoint: Punto di esecuzione del codice (es l'invocazione di un costruttore, esecuzione di un metodo o la gestione di una Exception) Advice: L'azione da compiere nel joinpoint. Pointcut: Contiene l'espressione che permette di individuare il joinpoint al quale vogliamo applicare l'advice Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 10. AOP elements Introduction: Permette l'aggiunta di interfacce e relativa implementazione a runtime, a oggetti già definiti. Target: Classe su cui agisce l'aspect con l'advice Weaving: L'azione con cui vengono legati gli “attori” AOP e le classi target. Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 11. AOP diagram Come opera l' AOP Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 12. Spring AOP Per permettere un utilizzo semplificato dell' AOP, Spring utilizza come Joinpoint l'esecuzione dei metodi. Questo significa che possiamo agire: prima, dopo, attorno ad un metodo, alla sollevazione di una eccezione, dopo l'esecuzione qualsiasi sia l' esito (finally), utilizziamo normali classi Java con annotazioni oppure con XML. Chi lavora nell' ombra per permetterci questa semplicità ? java.lang.reflect.Proxy oppure CGLIB Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 13. Spring AOP: take it easy Dobbiamo solo preoccuparci di decidere: -Cosa centralizzare/modularizzare ? -Quando deve entrare in azione ? Cosa posso ottenere: -Supporto al Domain Driven Design -Meno codice -Codice gestibile e manutenibile -Meno scuse per usare realmente l' OOP, non per spostare contenitori... Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 14. Spring AOP - Concorrenza @Aspect() @Order(0) Prima parte: public class ConcurrentAspect { private final ReadWriteLock lock = -Mi creo dei lock rientranti in new ReentrantReadWriteLock(); lettura e scrittura private final Lock rLock = lock.readLock(); private final Lock wLock = lock.writeLock(); -Annoto la classe con @Pointcut("execution (* isAvailable(..))") private void isAvailable() {} @Aspect @Pointcut("execution (* retainItem(..))") -Definisco con private void retainItem() {} l'annotazione @Pointcut("execution (* release(..))") @Pointcut le espressioni private void release() {} che mi indicano quando l' @Pointcut("release() || retainItem()") Aspect deve intervenire. private void releaseOrRetain() {} Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 15. Spring AOP - Concorrenza @Before("isAvailable()") Seconda parte: public void setReadLock() { rLock.lock(); Definisco riutilizzando i nomi } dei metodi sui quali ho @After("isAvailable()") annotato i @Pointcut la logica public void releaseReadLock() { rLock.unlock(); da eseguire con i lock } Con le annotazioni seguenti @Before("releaseOrRetain()") public void setWriteLock() { dichiaro quando voglio sia wLock.lock(); eseguita } @After("releaseOrRetain()") @Before public void releaseWriteLock() { @After wLock.unlock(); } @AfterReturning } @Around @AfterThrowing Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 16. Spring AOP – Advice Type Gli advice non solo ci permettono di eseguire logica nei punti definti dai pointcut, ma anche di ottenere @Before informazioni sulla esecuzione (classe target, metodo @After chiamato, argomenti passati, valore restituito) Con alcuni tipi di advice (around) anche di avere il @AfterReturning controllo sul flusso di esecuzione. La classe chiamante naturalmente non sa nulla di @Around quello che avviene, vede sempre una semplice classe .... @AfterThrowing Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 17. Spring AOP – Pointcut • execution Nei pointcut precedenti abbiamo visto come espressione • within per definire il punto di applicazione fosse l' esecuzione di • this un metodo con un determinato nome. • target Abbiamo a disposizione anche altri designatori di pointcut per avere il massimo controllo. • args • @target • @args • @within • @annotation ● bean Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 18. Spring AOP – JMX @ManagedResource("freshfruitstore:type=TimeExecutionManagedAspect") @Aspect() @Order(2) public class TimeExecutionManagedAspect { @ManagedAttribute Oltre a poter intervenire nel public long getAverageCallTime() { return (this.callCount > 0 flusso di escuzione, posso ? this.accumulatedCallTime / this.callCount : 0); } anche gestire gli Aspect @ManagedOperation public void resetCounters() { stessi con JMX, this.callCount = 0; } this.accumulatedCallTime = 0; esponendo come attributi o @ManagedAttribute operazioni, i normali public long getAverageCallTime() { return (this.callCount > 0 ? metodi dell' Aspect che è this.accumulatedCallTime / this.callCount : 0); } sempre una classe java. ... Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 19. Spring AOP – JMX ... @Around("within(it.mypackage.service.*Impl)") Posso quindi con JMX public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable { cambiare il if (this.isTimeExecutionEnabled) { StopWatch sw = new StopWatch(joinPoint.toString()); comportamento sw.start("invoke"); try { dell' Aspect a runtime return joinPoint.proceed(); } finally { sw.stop(); synchronized (this) { this.accumulatedCallTime += sw.getTotalTimeMillis(); } logger.info(sw.prettyPrint()); } } else { return joinPoint.proceed(); } } ... Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 20. ... Spring AOP – Introductions Una introduction mi permette di decorare un oggetto a runtime, aggiungendogli interfacce e relativa implementazione. Questo permette sia di evitare la duplicazione di una implementazione, sia di simulare l' ereditarietà multipla che java non ha. @Aspect public class ParallelepipedIntroduction { @DeclareParents(value = "org.springaop.chapter.four.introduction.Box", defaultImpl = Titanium.class) public Matter matter; @DeclareParents(value = "org.springaop.chapter.four.introduction.Box", defaultImpl = Cube.class) public GeometricForm geometricForm; } Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 21. ... Spring AOP – @Aspect Le annotazioni viste finora compresa la sintassi dei pointcut sono fornite da AspectJ import org.aspectj.lang.annotation.* ma sono assolutamente dentro il “contesto” di Spring e su dei bean di Spring. Vediamo ora invece cosa possiamo utilizzare di Spring (IoC) fuori dal “contesto” di Spring tramite AspectJ. Dovremo scendere a qualche compromesso... Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 22. DDD Aggregates Domain-Driven Design è un modo Entities di pensare le applicazioni. Modules Factories Suggerendo di concentrare l'attenzione sul dominio del Services Repositories problema, invitando a ragionare ad Value Objects oggetti e non in base a contenitori di dati da movimentare... Application Layer Infrastructure Layer UI Layer Domain Layer Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 23. DDD Nelle entità è concentrata public interface Customer extends NamedEntity { la logica di business, non public Address getAddress(); public ContactInformation getContact(); nei servizi che eseguono public void modifyContactInformation(ContactInformation contact); “procedure”... public void modifyAddress(Address address); public Boolean saveCustomer(); In questo modo i nostri public Boolean createOrder(); oggetti hanno dati e public Boolean saveOrder(); comportamenti, come public Order getOrder(); public List<Order> getOrders(); dovrebbe essere nelle } classi ad oggetti Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 24. SpringAOP +DDD +AspectJ @Configurable(dependencyCheck = true, autowire=Autowire.BY_TYPE) public class CustomerImpl implements Customer, Serializable { @Autowired public void setCustomerRepository(@Qualifier("customerRepository") CustomerRepository customerRepo) { this.customerRepository = customerRepository; } @Autowired public void setOrderRepository(@Qualifier("orderRepository") OrderRepository orderRepo) { this.orderRepository = orderRepo; } public Boolean createOrder() { Boolean result = false; if (order == null) { order = new OrderImpl.Builder(Constants.ID_NEW, new Date(), id .toString()).build(); result = true; } return result; } public Boolean saveCustomer() { return customerRepository.saveCustomer(this); } ... Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 25. SpringAOP +AspectJ Con @Configurable abbiamo dichiarando che alla classe verranno iniettate delle dipendenze benchè non sia uno spring bean. L' applicationContext di Spring conosce la classe semplicemente come un bean prototype. Per avere questa funzionalità abbiamo necessità di comunicare alla jvm il jar di spring da usare per il Load Time Weaving: -javaagent:<path>spring-agent.jar oppure configurare tomcat in questo modo per farlo al nostro posto: <Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader" useSystemClassLoaderAsParent="false"/> Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 26. Spring AOP +AspectJ Weaver Utilizzare l'AspectJ Weaver comporta un approccio diverso rispetto alla semplicità di SpringAOP vista sinora. Annotare delle classi come @Aspect e farli creare da Spring, significa rimanere comunque dentro l' IoC Container, così come definire pointcut su esecuzioni di metodi da parte di bean di Spring. Con il LTW stiamo dicendo a Spring di operare fuori dal suo “contesto”, per iniettare le dipendenze su oggetti non creati dall' IoC. Per utilizzare il LTW definiamo su un file per AspectJ le classi su cui deve operare e quali Aspect deve creare, Aspects che non sono bean creati da Spring... Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 27. LTW - aop.xml 100% AspectJ <!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd"> <aspectj> <weaver options="-showWeaveInfo -XmessageHandlerClass:org.springframework.aop.aspectj.AspectJWeaverMessageHandler"> <!-- only weave classes in our application-specific packages --> <include within="it.freshfruits.domain.entity.*"/> <include within="it.freshfruits.domain.factory.*"/> <include within="it.freshfruits.domain.service.*"/> <include within="it.freshfruits.domain.vo.*"/> <include within="it.freshfruits.application.repository.*"/> <exclude within="it.freshfruits.aspect.*"/> </weaver> <aspects> <aspect name="it.freshfruits.aspect.ConcurrentAspect" /> <aspect name="it.freshfruits.aspect.LogManagedAspect" /> <aspect name="it.freshfruits.aspect.TimeExecutionManagedAspect" /> </aspects> </aspectj> Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 28. Spring AOP +AspectJ Weaver Una volta che abbiamo le dipendenze in una entità del dominio, sia con l'iniezione delle dipendenze con il LTW, o tramite passaggio delle dipendenze come argomenti del costruttore ad opera di una factory, vediamo il risultato sulla UI. Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 29. DDD UI @Controller("customerController") public class CustomerController { @RequestMapping("/customer.create.page") public ModelAndView create(HttpServletRequest req) { return new ModelAndView("customer/create", "result", UiUtils.getCustomer(req).createOrder()); } @RequestMapping("/customer.order.page") public ModelAndView order(HttpServletRequest req) { return new ModelAndView("customer/order", "order", UiUtils.getOrder(req)); } @RequestMapping("/customer.items.page") public ModelAndView items(HttpServletRequest req) { return new ModelAndView("customer/items", "items", UiUtils.getOrder(req).getOrderItems()); } ... } I controller risultanti saranno completamente stateless e senza dipendenze, e con una semplice chiamata sulla entità. Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 30. DDD UI Handler Interceptor che pone nella HttpServletRequest l'entità customer utilizzata dal Customer Controller public class CustomerInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) throws Exception { req.setAttribute(Constants.CUSTOMER, customerFactory.getCurrentCustomer()); return true; } @Autowired private CustomerFactory customerFactory; } Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 31. Benefici OOP + AOP + DDD = Codice a oggetti Codice pulito Codice elegante Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 32. Spring MVC Handler Mapping 2 Request 1 3 Controller Dispatcher Servlet ModelAndView Response 4 5 ViewResolver 6 View Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 33. Form Controller @Controller("fruitController") @RequestMapping("/fruit.edit.admin") public class FruitController { @RequestMapping(method = RequestMethod.POST) public String processSubmit(@ModelAttribute("fruit") FruitMap fruit, BindingResult result, SessionStatus status) { validator.validate(fruit, result); if (result.hasErrors()) { return "userForm"; } else { fruit.save(); status.setComplete(); return "redirect:role.list.admin"; } } @InitBinder() public void initBinder(WebDataBinder binder) throws Exception { binder.registerCustomEditor(String.class, new StringTrimmerEditor(false)); } @RequestMapping(method = RequestMethod.GET) public String setupForm(@RequestParam(required = false, value = "id") Integer id, ModelMap model) { model.addAttribute(Constants.FRUIT, id == null ? new FruitMap() : fruitRepository.getFruitType(id)); return "role/form"; } @Autowired @Qualifier("fruitRepository") private FruitTypeRepository fruitRepository; @Autowired @Qualifier("fruitValidator") FruitValidator validator; } Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 34. MultiAction Controller @Controller("customerController") public class CustomerController { @RequestMapping("/customer.create.page") public ModelAndView create(HttpServletRequest req) { return new ModelAndView("customer/create", "result", UiUtils.getCustomer(req).createOrder()); } @RequestMapping("/customer.save.page") public ModelAndView save(HttpServletRequest req) { return new ModelAndView("customer/save", "result", UiUtils.getCustomer(req).saveOrder()); } @RequestMapping("/customer.show.page") public ModelAndView show(HttpServletRequest req) { return new ModelAndView("customer/show", "customer", UiUtils.getCustomer(req)); } @RequestMapping("/customer.order.page") public ModelAndView order(HttpServletRequest req) { return new ModelAndView("customer/order", "order", UiUtils.getOrder(req)); } @RequestMapping("/customer.items.page") public ModelAndView items(HttpServletRequest req) { return new ModelAndView("customer/items", "items", UiUtils.getOrder(req).getOrderItems()); } @RequestMapping("/customer.remove.page") public ModelAndView remove(@RequestParam("id") String id, HttpServletRequest req) throws Exception { Order order = UiUtils.getOrder(req); return order.removeOrderItem(order.getId().toString(), id) ? new ModelAndView("customer/items", "items", order.getOrderItems()) : new ModelAndView("customer/remove", "result", false); } } Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 35. Configuration <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <context:component-scan base-package="it.freshfruits.ui"/> <context:annotation-config/> <bean name="urlMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> <property name="interceptors"> <list> <ref bean="customerInterceptor"/> </list> </property> </bean> <bean name="customerInterceptor" class="it.freshfruits.ui.interceptor.CustomerInterceptor"/> </beans> Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 36. Spring Security <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:sec="http://www.springframework.org/schema/security" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.4.xsd"> <sec:http> <sec:intercept-url pattern="/log*.jsp" filters="none" /> <sec:intercept-url pattern="/*.page" access="ROLE_USER" /> <sec:intercept-url pattern="/*.admin" access="ROLE_ADMIN" /> <sec:form-login login-page="/login.jsp" default-target-url="/" login-processing-url="/j_security_check" authentication-failure-url="/loginError.jsp" /> <sec:logout logout-url="/logout.jsp" invalidate-session="true" logout-success-url="/login.jsp" /> <sec:remember-me /> <sec:intercept-url pattern="*.htm" access="ROLE_USER,ROLE_ANONYMOUS" /> <sec:intercept-url pattern="*.page" access="ROLE_USER,ROLE_ADMIN" /> <sec:intercept-url pattern="*.edit" access="ROLE_USER,ROLE_ADMIN" /> <sec:intercept-url pattern="*.admin" access="ROLE_ADMIN" /> </sec:http> <sec:authentication-provider user-service-ref="sffsUserDetailservice"><sec:password-encoder hash="sha" /></sec:authentication-provider> <bean id="accessDecisionManager" class="org.springframework.security.vote.AffirmativeBased"> <property name="decisionVoters"> <list> <bean class="org.springframework.security.vote.RoleVoter" /> <bean class="org.springframework.security.vote.AuthenticatedVoter" /> </list> </property> </bean> <bean id="sffsUserDetailservice" class="it.freshfruits.security.AuthenticationJdbcDaoImpl" p:rolePrefix="ROLE_" p:dataSource-ref="dataSource" p:usersByUsernameQuery="SELECT username, password, enabled FROM authentication WHERE username = ?" p:authoritiesByUsernameQuery="SELECT username, authority FROM roles WHERE username = ?" /> <sec:global-method-security access-decision-manager-ref="accessDecisionManager"> <sec:protect-pointcut expression="execution(* it.freshfruits.domain.entity.*.*(..))" access="ROLE_USER,ROLE_ADMIN" /> </sec:global-method-security> ... </beans> Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 37. WEB.XML ... <context-param> <param-name>webAppRootKey</param-name> <param-value>springFreshFruitsStore.root</param-value> </context-param> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/conf/spring/sffs-*.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <servlet> <servlet-name>sffs</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping><servlet-name>sffs</servlet-name><url-pattern>*.page</url-pattern></servlet-mapping> <servlet-mapping><servlet-name>sffs</servlet-name><url-pattern>*.edit</url-pattern></servlet-mapping> <servlet-mapping><servlet-name>sffs</servlet-name><url-pattern>*.admin</url-pattern></servlet-mapping> <servlet-mapping><servlet-name>sffs</servlet-name><url-pattern>*.htm</url-pattern></servlet-mapping> ... Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 38. Jsp paginated list <%@ include file="/WEB-INF/jsp/taglibs.jsp"%> <tag:pager href="user.list.page"/> <div> <div align="center"><span><spring:message code="ui.users"/></span></div> <c:if test="${msg ne ''}">${msg}</c:if> <table class="list"> <thead><tr><th align="left"><spring:message code="ui.user.username"/></th></tr></thead> <tbody> <c:forEach var="user" items="${users}" varStatus="status"> <c:choose> <c:when test="${status.count % 2 == 0}"> <tr class="table-row-dispari"></c:when> <c:otherwise> <tr class="table-row-pari"></c:otherwise> </c:choose> <td align="left">${user.username}</td> <td align="center"> <a href="user.roles.page?sid=${user.id}"><img border="0" title="<spring:message code="ui.action.view"/>" alt="<spring:message code="ui.action.view"/>" src="img/view.png"/></a> </td> <td align="center"> <a href="user.detail.page?sid=${user.id}"><img border="0" title="<spring:message code="ui.action.edit"/>" alt="<spring:message code="ui.action.edit"/>" src="img/edit.png"/></a></td> </tr> </c:forEach> </tbody> </table> </div> <br/> <tag:pager href="user.list.page"/> <div align="center"> <input type="image" src="img/add.png" title="<spring:message code="ui.action.user.new"/>" alt="<spring:message code="ui.action.user.new"/>" onclick="location.href = 'user.edit.page'" value="<spring:message code="ui.action.user.new"/>"/> </div> Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 39. Spring MVC Portlet Portlet Deja vu ? Handler Mapping 2 1 3 Controller Dispatcher Portlet ModelAndView 4 5 ViewResolver 6 ViewRenderer Servlet Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 40. Spring riutilizza gli stessi concetti della parte MVC Servlet, traslando dove serve le richieste Portlet (action o render) in Servlet, permettendo il riuso dei controller. Spring fornisce una NativeWebRequest che maschera il tipo di richiesta, questo approccio ci permette di scrivere controller che virtualmente possono non sapere dentro cosa stanno girando. In pratica, i problemi li può creare il portal server... Nonostante i problemi con il portal server, è comunque possibile riutilizzare la gran parte del codice scritto per una webapp normale. Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 41. Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 42. Se abbiamo disegnato bene la nostra webapp con SpringMVC, non è troppo complesso portarlo su SpringMVC Portlet Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 43. Spring AOP Book Maggiori informazioni a febbraio su : http://www.packtpub.com Un enorme grazie a Stefano Sanna per il supporto durante la scrittura del libro. Se è stato terminato è grazie al suo contributo che non è mai mancato. Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 44. Domande ? Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009
  • 45. Grazie per l'attenzione ! Massimiliano Dessì desmax74 at yahoo.it http://jroller.com/desmax http://www.linkedin.com/in/desmax74 http://wiki.java.net/bin/view/People/MassimilianoDessi http://www.jugsardegna.org/vqwiki/jsp/Wiki?MassimilianoDessi Spring Framework Italian User Group http://it.groups.yahoo.com/group/SpringFramework-it Massimiliano Dessì - desmax74@yahoo.it Milano - 30/01/2009