SlideShare ist ein Scribd-Unternehmen logo
1 von 31
Jersey + Guice + AOP




                Domenico Briganti
                dometec@gmail.com
Chi sono?
@PerRequest
public class Presentation {

    @GET
    @Path("/JugMilano/People/DomenicoBriganti")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getUserDetails() {

     UserDetails userdet = new UserDetails();
     userdet.setCompany("Eidon srl");
     userdet.setEmail("dometec@gmail.com");
     userdet.setLinkedin("http://www.linkedin.com/in/dometec");
     userdet.setBlog("http://tipsaboutmywork.blogspot.com/");
     ...

    return Response.ok(userdet).build();

}


                                        JUG Milano – Meeting #48   2
Agenda
JAX-RS
Jersey con Guice/AOP

Demos:
Log delle richieste
Trim dei parametri Stringa in ingresso
Evitare chiamate identiche su un cluster
Transazioni
Login cookie


                               JUG Milano – Meeting #48   3
JAX-RS
Java API for RESTful Web Services
Release 1.1, JSR 311, 2009, JEE6 Full
Release futura 2.0, JSR 339, (EDR2 2012), JEE7
Package: javax.ws.rest
Implementazioni: Jersey (RI), Apache CXF,
  RESTEasy, Apache Wink




                              JUG Milano – Meeting #48   4
Jersey
Open source, RI for JAX-RS

Jersey 1.x (1.13b1) implements JAX-RS 1.1

Jersey 2.x (mileston 3) implements JAX-RS 2

CDDL + GPL 1.1




                              JUG Milano – Meeting #48   5
Jersey Hello World
import   javax.ws.rs.GET;
import   javax.ws.rs.Path;
import   javax.ws.rs.PathParam;
import   javax.ws.rs.core.Response;

@Path("/hello")
public class HelloWorldService {

          @GET
          @Path("/{param}")
          public Response getMsg(@PathParam("param") String msg) {

                  String output = "Echo: " + msg;
                  return Response.ok(output).build();

          }

}




                                             JUG Milano – Meeting #48   6
JAX-RS Annotation
Verbi HTTP: @GET, @POST, @PUT, @DELETE,
 @OPTION, @HEAD

Identificazione risorse: @Path

Input: @PathParam, @QueryParam, @MatrixParam,
  @HeaderParam, @CookieParam. @FormParam.
  @DefaultValue. MultivaluedMap<String, String>

Content negotiation: @Produces, @Consume


                                 JUG Milano – Meeting #48   7
JAX-RS Annotation e Facility
Ambiente: @Context (ServletConfig, ServletContext,
 HttpServletRequest, HttpServletResponse,
 SecurityContext, UriInfo, HttpHeaders)

Mapper, MessageBodyWriters,
 MessageBodyReaders: @Provider

ResponseBuilder e UriBuilder




                               JUG Milano – Meeting #48   8
DEMO 0

  “Esecuzione” della
slide di presentazione




                JUG Milano – Meeting #48   9
Jersey-Guice integration
           <listener>
               <listener-class>org.example.demo.GuiceConfig</listener-class>
           </listener>

           <filter>
               <filter-name>GuiceFilter</filter-name>
web.xml:
web.xml




               <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
           </filter>

           <filter-mapping>
               <filter-name>GuiceFilter</filter-name>
               <url-pattern>/services/*</url-pattern>
               <url-pattern>/application.wadl</url-pattern>
               <url-pattern>/application.wadl/*</url-pattern>
           </filter-mapping>

           package org.example.demo;

           public class GuiceConfig extends GuiceServletContextListener {

            @Override
listener




            protected Injector getInjector() {

              return Guice.createInjector(new JerseyServletModule() {
                @Override
                protected void configureServlets() {

                  Map<String, String> params = new HashMap<String, String>();

                  params.put(PackagesResourceConfig.PROPERTY_PACKAGES, "org.example.demo");
                  params.put(ResourceConfig.FEATURE_TRACE, "true");
                  params.put(ResourceConfig.FEATURE_TRACE_PER_REQUEST, "true");
                  ...



                                                                                JUG Milano – Meeting #48   10
Demo 1

Log delle richieste




              JUG Milano – Meeting #48   11
Demo 1 – Log delle richieste (interc.)
public class LogCall implements MethodInterceptor {

    public Object invoke(MethodInvocation invocation) throws Throwable {

        Logger logger = LoggerFactory.getLogger(invocation.getThis().getClass());

        String arg = Joiner.on(", ").useForNull("null").join(invocation.getArguments());
        logger.debug("{} ({}).", invocation.getMethod().getName(), arg);

        Object result = invocation.proceed();

        logger.trace("Output: {}.", result);

        return result;

    }

}




                                                       JUG Milano – Meeting #48        12
Demo 1 – Log delle richieste (bind)
public class GuiceConfig extends GuiceServletContextListener {

 @Override
 protected Injector getInjector() {

   return Guice.createInjector(new JerseyServletModule() {

     @Override
     protected void configureServlets() {

       Map<String, String> params = new HashMap<String, String>();

       params.put(PackagesResourceConfig.PROPERTY_PACKAGES, "org.example.demo");
       ...

       filter("/*").through(GuiceContainer.class, params);

       install(new Module() {

         public void configure(Binder binder) {

           LogCall logCall = new LogCall();
           TrimAndNullInterceptor trimAndNullableInterceptor = new TrimAndNullInterceptor();

           bindInterceptor(
           Matchers.annotatedWith(Path.class),
           Matchers.annotatedWith(GET.class).or(Matchers.annotatedWith(POST.class))
           .or(Matchers.annotatedWith(PUT.class)).or(Matchers.annotatedWith(DELETE.class)),
           trimAndNullableInterceptor, logCall);




                                                             JUG Milano – Meeting #48          13
Demo 2 – Trim parametri (interc.)
public class TrimAndNullInterceptor implements MethodInterceptor {

    public Object invoke(MethodInvocation invocation) throws Throwable {

        for (int i = 0; i < invocation.getArguments().length; i++) {

            if (invocation.getArguments()[i] != null &&
                invocation.getArguments()[i] instanceof String) {

                 String sparam = (String) invocation.getArguments()[i];

                 String trim = sparam.trim();

                 if (trim.isEmpty())
                      invocation.getArguments()[i] = null;
                 else
                      invocation.getArguments()[i] = trim;
        }

    }

    return invocation.proceed();

    }
}




                                                        JUG Milano – Meeting #48   14
Demo 2 – Trim parametri (bind)
public class GuiceConfig extends GuiceServletContextListener {

 @Override
 protected Injector getInjector() {

   return Guice.createInjector(new JerseyServletModule() {

     @Override
     protected void configureServlets() {

       Map<String, String> params = new HashMap<String, String>();

       params.put(PackagesResourceConfig.PROPERTY_PACKAGES, "org.example.demo");
       ...

       filter("/*").through(GuiceContainer.class, params);

       install(new Module() {

         public void configure(Binder binder) {

           LogCall logCall = new LogCall();
           TrimAndNullInterceptor trimAndNullableInterceptor = new TrimAndNullInterceptor();

           bindInterceptor(
           Matchers.annotatedWith(Path.class),
           Matchers.annotatedWith(GET.class).or(Matchers.annotatedWith(POST.class))
           .or(Matchers.annotatedWith(PUT.class)).or(Matchers.annotatedWith(DELETE.class)),
           trimAndNullableInterceptor, logCall);




                                                             JUG Milano – Meeting #48          15
Evitare richieste duplicate
Problemi:
  Ristrasmissioni
  Doppi submit (anche Tripli...) da browser
  Timeout lato client che scatena altre prove di richieste


Rimedi:
  Hashtable con chiamate attualmente in corso
  429 Too Many Requests (RFC 6585)
  Infinispan con lock condiviso per sistemi cluster



                                     JUG Milano – Meeting #48   16
Demo 3 – Richieste duplicate (uso)
@POST
@UniqueCallOnCluster
public Response getAccountBalance(@FormParam("fromuser")...


@POST
@UniqueCallOnCluster
public Response getAccountBalance(@KeyParameter
@FormParam("fromuser")...




                                      JUG Milano – Meeting #48   17
Demo 3 – Richieste duplicate (Inter.)
public class UniqueCallOnClusterInterceptor implements MethodInterceptor {
   ...
   public Object invoke(MethodInvocation invocation) throws Throwable {

     String classname = invocation.getMethod().getDeclaringClass().getSimpleName();
     String methodName = invocation.getMethod().getName();
     String key = classname + "_" + methodName + "_" + extractParameterValue(invocation);

     TransactionManager tm = keyCallOnClusterService.getTransactionManager();

     tm.begin();
     boolean success = keyCallOnClusterService.lock(key);

     if (!success) {
          logger.info("Non posso effettuare il lock sul cluster per la chiave {}.", key);
          return Response.status(429).entity("Another call with same parameter is in progress.").build();
     }

     String runningServer = (String) keyCallOnClusterService.get(key);
     if (runningServer != null) {
          logger.info("Chiamata già in corso, server {}.", runningServer);
          return Response.status(429).entity("Another call with same parameter is in progress.").build();
     }

     keyCallOnClusterService.put(key, "todo-hostname");
     tm.commit();
     ...
     return invocation.proceed();
     ...

     keyCallOnClusterService.remove(key);

}



                                                                JUG Milano – Meeting #48               18
Demo 3 – Richieste duplicate (bind)
public class GuiceConfig extends GuiceServletContextListener {

 @Override
 protected Injector getInjector() {

   return Guice.createInjector(new JerseyServletModule() {

     @Override
     protected void configureServlets() {

       Map<String, String> params = new HashMap<String, String>();

       params.put(PackagesResourceConfig.PROPERTY_PACKAGES, "org.example.demo");
       ...

       filter("/*").through(GuiceContainer.class, params);

       install(new Module() {

         public void configure(Binder binder) {

             UniqueCallOnClusterInterceptor uniqueCallOnClusterInterceptor =
                  new UniqueCallOnClusterInterceptor();
             requestInjection(uniqueCallOnClusterInterceptor);
             bindInterceptor(Matchers.any(), Matchers.annotatedWith(UniqueCallOnCluster.class),
                  uniqueCallOnClusterInterceptor);




                                                             JUG Milano – Meeting #48         19
Transazioni con AOP




             JUG Milano – Meeting #48   20
Transazioni con AOP




             JUG Milano – Meeting #48   21
Transazioni con AOP




             JUG Milano – Meeting #48   22
Demo 4 – Transazioni (uso)
package org.example.demo.controller;


@PerRequest
@Transactional
@Path("services/transactionalresource3")
public class TransactionalResource3Write extends AbstractTransactionalResource {

   @Inject
   public TransactionalResource3Write() {
   }

   @POST
   @Produces("text/plain")
   public String get() {

   ...

                                                  JUG Milano – Meeting #48         23
Demo 4 – Transazioni (uso)
package org.example.demo.controller;

@PerRequest
@Transactional(TransactionType.ReadOnly)
@Path("services/transactionalresource1")
public class TransactionalResource1ReadOnly extends AbstractTransactionalResource {

    @Inject
    public TransactionalResource1ReadOnly() {
    }

    @GET
    @Produces("text/plain")
    @SuppressWarnings("unchecked")
    public String get() {

        List<DatabaseLog> list = getSession().createCriteria(DatabaseLog.class).list();

        if (list.size() == 0)
              return "No record!";
                                                         JUG Milano – Meeting #48         24
Demo 4 – Transazioni (uso)
package org.example.demo.controller;

@PerRequest
@Transactional(TransactionType.RequiredNew)
@Path("services/transactionalresource5")
public class TransactionalResource5ReqNew extends AbstractTransactionalResource {

    @Inject
    public TransactionalResource5ReqNew() {
    }

    ...




                                                      JUG Milano – Meeting #48      25
Demo 4 – Transazioni (uso)
public abstract class AbstractTransactionalResource {
   private Session session;

    @NoTransactional
    public void setSession(Session session) {
       this.session = session;              }

    @NoTransactional
    public Session getSession()             {
       return session;                      }

    @Override
    @NoTransactional
    protected void finalize() throws Throwable {
        super.finalize();                      }

}
                                                   JUG Milano – Meeting #48   26
Demo 4 – Transazioni 1/2 (interc.)
public class TransactionInterceptor implements MethodInterceptor {

     private final ThreadLocal<Stack<Session>> sessionThreadLocal;

          public Object invoke(MethodInvocation invocation) throws Throwable {
               ...
               Transactional transactional =
invocation.getMethod().getDeclaringClass().getAnnotation(Transactional.class);
               ...

               Stack<Session> sessionStack = sessionThreadLocal.get();
               Transaction transaction = null;
               Session session = null;
               if (!sessionStack.isEmpty())
                    session = sessionStack.peek();

               if (session == null || transType.equals(TransactionType.RequiredNew)) {

                    boolean readonly = false;
                    readonly = transType.equals(TransactionType.ReadOnly);
                    session = hibernateSessionService.openSession(readonly);
                    transaction = session.getTransaction();
                    transaction.begin();
                    sessionStack.push(session);
               }

               Session oldSession = null;
               AbstractTransactionalResource service = ((AbstractTransactionalResource)
invocation.getThis());
               oldSession = service.getSession();
               service.setSession(session);

               Object result = invocation.proceed();



                                                                JUG Milano – Meeting #48   27
Demo 4 – Transazioni 2/2 (interc.)
         try {

              Object result = invocation.proceed();

              if (transaction != null) {
                   session.flush();
                   transaction.commit();
              }

              return result;

         } catch (Exception e) {

              transaction.rollback();
              throw e;

         } finally {

              if (transaction != null) {
                   hibernateSessionService.closeSession(session);
                   sessionStack.pop();
                   if (sessionStack.isEmpty())
                        sessionThreadLocal.remove();
              }

              service.setSession(oldSession);

         }

    }

}




                                                               JUG Milano – Meeting #48   28
Demo 4 – Transazioni (bind)
public class GuiceConfig extends GuiceServletContextListener {

 @Override
 protected Injector getInjector() {

   return Guice.createInjector(new JerseyServletModule() {

     @Override
     protected void configureServlets() {

       Map<String, String> params = new HashMap<String, String>();

       params.put(PackagesResourceConfig.PROPERTY_PACKAGES, "org.example.demo");
       ...

       filter("/*").through(GuiceContainer.class, params);

       install(new Module() {

         public void configure(Binder binder) {

           TransactionInterceptor transactionInterceptor =
             new TransactionInterceptor();
           requestInjection(transactionInterceptor);
           bindInterceptor(Matchers.annotatedWith(Transactional.class),
             Matchers.not(Matchers.annotatedWith(NoTransactional.class)),
             TransactionInterceptor);




                                                             JUG Milano – Meeting #48   29
Demo 5 - Login Cookie (bind)
Annotation:
  AuthenticatedUser
  ApplicationRolesAllowed
Provider:
  AuthenticatedUserProvider
Exception e ExceptionMapper:
  NotAuthenticatedException(+Mapper)
  NotAuthorizedException(+Mapper)
Cookie: LoginCookieManager
Utente: DemoPrincipal
Interceptor: ApplicationRolesAllowedInterceptor
                                JUG Milano – Meeting #48   30
Grazie!

Domande??




Riferimenti:
http://jersey.java.net
http://code.google.com/p/google-guice/
Demo webapp:
 https://github.com/dometec/shadedcode/tree/master/demo-webapp




                                         JUG Milano – Meeting #48   31

Weitere ähnliche Inhalte

Was ist angesagt?

Advanced Java Practical File
Advanced Java Practical FileAdvanced Java Practical File
Advanced Java Practical File
Soumya Behera
 
망고100 보드로 놀아보자 19
망고100 보드로 놀아보자 19망고100 보드로 놀아보자 19
망고100 보드로 놀아보자 19
종인 전
 
Java 7 at SoftShake 2011
Java 7 at SoftShake 2011Java 7 at SoftShake 2011
Java 7 at SoftShake 2011
julien.ponge
 
Java весна 2013 лекция 2
Java весна 2013 лекция 2Java весна 2013 лекция 2
Java весна 2013 лекция 2
Technopark
 
Software Testing - Invited Lecture at UNSW Sydney
Software Testing - Invited Lecture at UNSW SydneySoftware Testing - Invited Lecture at UNSW Sydney
Software Testing - Invited Lecture at UNSW Sydney
julien.ponge
 

Was ist angesagt? (20)

Guice2.0
Guice2.0Guice2.0
Guice2.0
 
Слава Бобик «NancyFx для самых маленьких»
Слава Бобик «NancyFx для самых маленьких»Слава Бобик «NancyFx для самых маленьких»
Слава Бобик «NancyFx для самых маленьких»
 
Advanced Java Practical File
Advanced Java Practical FileAdvanced Java Practical File
Advanced Java Practical File
 
京都Gtugコンパチapi
京都Gtugコンパチapi京都Gtugコンパチapi
京都Gtugコンパチapi
 
망고100 보드로 놀아보자 19
망고100 보드로 놀아보자 19망고100 보드로 놀아보자 19
망고100 보드로 놀아보자 19
 
Spock and Geb in Action
Spock and Geb in ActionSpock and Geb in Action
Spock and Geb in Action
 
Java practice programs for beginners
Java practice programs for beginnersJava practice programs for beginners
Java practice programs for beginners
 
The Ring programming language version 1.5.3 book - Part 78 of 184
The Ring programming language version 1.5.3 book - Part 78 of 184The Ring programming language version 1.5.3 book - Part 78 of 184
The Ring programming language version 1.5.3 book - Part 78 of 184
 
What’s new in C# 6
What’s new in C# 6What’s new in C# 6
What’s new in C# 6
 
#5 (Remote Method Invocation)
#5 (Remote Method Invocation)#5 (Remote Method Invocation)
#5 (Remote Method Invocation)
 
Dagger & rxjava & retrofit
Dagger & rxjava & retrofitDagger & rxjava & retrofit
Dagger & rxjava & retrofit
 
Bang-Bang, you have been hacked - Yonatan Levin, KolGene
Bang-Bang, you have been hacked - Yonatan Levin, KolGeneBang-Bang, you have been hacked - Yonatan Levin, KolGene
Bang-Bang, you have been hacked - Yonatan Levin, KolGene
 
The Ring programming language version 1.10 book - Part 94 of 212
The Ring programming language version 1.10 book - Part 94 of 212The Ring programming language version 1.10 book - Part 94 of 212
The Ring programming language version 1.10 book - Part 94 of 212
 
The Ring programming language version 1.8 book - Part 95 of 202
The Ring programming language version 1.8 book - Part 95 of 202The Ring programming language version 1.8 book - Part 95 of 202
The Ring programming language version 1.8 book - Part 95 of 202
 
The Ring programming language version 1.5.2 book - Part 13 of 181
The Ring programming language version 1.5.2 book - Part 13 of 181The Ring programming language version 1.5.2 book - Part 13 of 181
The Ring programming language version 1.5.2 book - Part 13 of 181
 
Java 7 at SoftShake 2011
Java 7 at SoftShake 2011Java 7 at SoftShake 2011
Java 7 at SoftShake 2011
 
Current State of Coroutines
Current State of CoroutinesCurrent State of Coroutines
Current State of Coroutines
 
Java 7 JUG Summer Camp
Java 7 JUG Summer CampJava 7 JUG Summer Camp
Java 7 JUG Summer Camp
 
Java весна 2013 лекция 2
Java весна 2013 лекция 2Java весна 2013 лекция 2
Java весна 2013 лекция 2
 
Software Testing - Invited Lecture at UNSW Sydney
Software Testing - Invited Lecture at UNSW SydneySoftware Testing - Invited Lecture at UNSW Sydney
Software Testing - Invited Lecture at UNSW Sydney
 

Ähnlich wie Jersey Guice AOP

JJUG CCC 2011 Spring
JJUG CCC 2011 SpringJJUG CCC 2011 Spring
JJUG CCC 2011 Spring
Kiyotaka Oku
 
Jdk 7 4-forkjoin
Jdk 7 4-forkjoinJdk 7 4-forkjoin
Jdk 7 4-forkjoin
knight1128
 
名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン
名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン
名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン
Tsuyoshi Yamamoto
 
服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript
Qiangning Hong
 
Overview of Android Infrastructure
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android Infrastructure
Alexey Buzdin
 
Overview of Android Infrastructure
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android Infrastructure
C.T.Co
 

Ähnlich wie Jersey Guice AOP (20)

比XML更好用的Java Annotation
比XML更好用的Java Annotation比XML更好用的Java Annotation
比XML更好用的Java Annotation
 
Codemotion appengine
Codemotion appengineCodemotion appengine
Codemotion appengine
 
Anti patterns
Anti patternsAnti patterns
Anti patterns
 
Google App Engine Developer - Day3
Google App Engine Developer - Day3Google App Engine Developer - Day3
Google App Engine Developer - Day3
 
Fun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksFun Teaching MongoDB New Tricks
Fun Teaching MongoDB New Tricks
 
JJUG CCC 2011 Spring
JJUG CCC 2011 SpringJJUG CCC 2011 Spring
JJUG CCC 2011 Spring
 
Android workshop
Android workshopAndroid workshop
Android workshop
 
Clean coding-practices
Clean coding-practicesClean coding-practices
Clean coding-practices
 
Paradigmas de linguagens de programacao - aula#9
Paradigmas de linguagens de programacao - aula#9Paradigmas de linguagens de programacao - aula#9
Paradigmas de linguagens de programacao - aula#9
 
E:\Plp 2009 2\Plp 9
E:\Plp 2009 2\Plp 9E:\Plp 2009 2\Plp 9
E:\Plp 2009 2\Plp 9
 
Ten useful JavaScript tips & best practices
Ten useful JavaScript tips & best practicesTen useful JavaScript tips & best practices
Ten useful JavaScript tips & best practices
 
Testing in android
Testing in androidTesting in android
Testing in android
 
Jdk 7 4-forkjoin
Jdk 7 4-forkjoinJdk 7 4-forkjoin
Jdk 7 4-forkjoin
 
名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン
名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン
名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン
 
Struts2 notes
Struts2 notesStruts2 notes
Struts2 notes
 
服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript
 
Introduccion a AspectJ
Introduccion a AspectJIntroduccion a AspectJ
Introduccion a AspectJ
 
Overview of Android Infrastructure
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android Infrastructure
 
Overview of Android Infrastructure
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android Infrastructure
 
Diifeerences In C#
Diifeerences In C#Diifeerences In C#
Diifeerences In C#
 

Mehr von Domenico Briganti (8)

Software Testing e TDD
Software Testing e TDDSoftware Testing e TDD
Software Testing e TDD
 
XSLT
XSLT XSLT
XSLT
 
XSL-FO
XSL-FOXSL-FO
XSL-FO
 
XML Schema (XSD)
XML Schema (XSD)XML Schema (XSD)
XML Schema (XSD)
 
Xml annessi e connessi
Xml annessi e connessiXml annessi e connessi
Xml annessi e connessi
 
Java codestyle & tipstricks
Java codestyle & tipstricksJava codestyle & tipstricks
Java codestyle & tipstricks
 
Testing
TestingTesting
Testing
 
Xml Xslt
Xml  XsltXml  Xslt
Xml Xslt
 

Kürzlich hochgeladen

Kürzlich hochgeladen (20)

Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Cyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdfCyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdf
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 

Jersey Guice AOP

  • 1. Jersey + Guice + AOP Domenico Briganti dometec@gmail.com
  • 2. Chi sono? @PerRequest public class Presentation { @GET @Path("/JugMilano/People/DomenicoBriganti") @Produces(MediaType.APPLICATION_JSON) public Response getUserDetails() { UserDetails userdet = new UserDetails(); userdet.setCompany("Eidon srl"); userdet.setEmail("dometec@gmail.com"); userdet.setLinkedin("http://www.linkedin.com/in/dometec"); userdet.setBlog("http://tipsaboutmywork.blogspot.com/"); ... return Response.ok(userdet).build(); } JUG Milano – Meeting #48 2
  • 3. Agenda JAX-RS Jersey con Guice/AOP Demos: Log delle richieste Trim dei parametri Stringa in ingresso Evitare chiamate identiche su un cluster Transazioni Login cookie JUG Milano – Meeting #48 3
  • 4. JAX-RS Java API for RESTful Web Services Release 1.1, JSR 311, 2009, JEE6 Full Release futura 2.0, JSR 339, (EDR2 2012), JEE7 Package: javax.ws.rest Implementazioni: Jersey (RI), Apache CXF, RESTEasy, Apache Wink JUG Milano – Meeting #48 4
  • 5. Jersey Open source, RI for JAX-RS Jersey 1.x (1.13b1) implements JAX-RS 1.1 Jersey 2.x (mileston 3) implements JAX-RS 2 CDDL + GPL 1.1 JUG Milano – Meeting #48 5
  • 6. Jersey Hello World import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.core.Response; @Path("/hello") public class HelloWorldService { @GET @Path("/{param}") public Response getMsg(@PathParam("param") String msg) { String output = "Echo: " + msg; return Response.ok(output).build(); } } JUG Milano – Meeting #48 6
  • 7. JAX-RS Annotation Verbi HTTP: @GET, @POST, @PUT, @DELETE, @OPTION, @HEAD Identificazione risorse: @Path Input: @PathParam, @QueryParam, @MatrixParam, @HeaderParam, @CookieParam. @FormParam. @DefaultValue. MultivaluedMap<String, String> Content negotiation: @Produces, @Consume JUG Milano – Meeting #48 7
  • 8. JAX-RS Annotation e Facility Ambiente: @Context (ServletConfig, ServletContext, HttpServletRequest, HttpServletResponse, SecurityContext, UriInfo, HttpHeaders) Mapper, MessageBodyWriters, MessageBodyReaders: @Provider ResponseBuilder e UriBuilder JUG Milano – Meeting #48 8
  • 9. DEMO 0 “Esecuzione” della slide di presentazione JUG Milano – Meeting #48 9
  • 10. Jersey-Guice integration <listener> <listener-class>org.example.demo.GuiceConfig</listener-class> </listener> <filter> <filter-name>GuiceFilter</filter-name> web.xml: web.xml <filter-class>com.google.inject.servlet.GuiceFilter</filter-class> </filter> <filter-mapping> <filter-name>GuiceFilter</filter-name> <url-pattern>/services/*</url-pattern> <url-pattern>/application.wadl</url-pattern> <url-pattern>/application.wadl/*</url-pattern> </filter-mapping> package org.example.demo; public class GuiceConfig extends GuiceServletContextListener { @Override listener protected Injector getInjector() { return Guice.createInjector(new JerseyServletModule() { @Override protected void configureServlets() { Map<String, String> params = new HashMap<String, String>(); params.put(PackagesResourceConfig.PROPERTY_PACKAGES, "org.example.demo"); params.put(ResourceConfig.FEATURE_TRACE, "true"); params.put(ResourceConfig.FEATURE_TRACE_PER_REQUEST, "true"); ... JUG Milano – Meeting #48 10
  • 11. Demo 1 Log delle richieste JUG Milano – Meeting #48 11
  • 12. Demo 1 – Log delle richieste (interc.) public class LogCall implements MethodInterceptor { public Object invoke(MethodInvocation invocation) throws Throwable { Logger logger = LoggerFactory.getLogger(invocation.getThis().getClass()); String arg = Joiner.on(", ").useForNull("null").join(invocation.getArguments()); logger.debug("{} ({}).", invocation.getMethod().getName(), arg); Object result = invocation.proceed(); logger.trace("Output: {}.", result); return result; } } JUG Milano – Meeting #48 12
  • 13. Demo 1 – Log delle richieste (bind) public class GuiceConfig extends GuiceServletContextListener { @Override protected Injector getInjector() { return Guice.createInjector(new JerseyServletModule() { @Override protected void configureServlets() { Map<String, String> params = new HashMap<String, String>(); params.put(PackagesResourceConfig.PROPERTY_PACKAGES, "org.example.demo"); ... filter("/*").through(GuiceContainer.class, params); install(new Module() { public void configure(Binder binder) { LogCall logCall = new LogCall(); TrimAndNullInterceptor trimAndNullableInterceptor = new TrimAndNullInterceptor(); bindInterceptor( Matchers.annotatedWith(Path.class), Matchers.annotatedWith(GET.class).or(Matchers.annotatedWith(POST.class)) .or(Matchers.annotatedWith(PUT.class)).or(Matchers.annotatedWith(DELETE.class)), trimAndNullableInterceptor, logCall); JUG Milano – Meeting #48 13
  • 14. Demo 2 – Trim parametri (interc.) public class TrimAndNullInterceptor implements MethodInterceptor { public Object invoke(MethodInvocation invocation) throws Throwable { for (int i = 0; i < invocation.getArguments().length; i++) { if (invocation.getArguments()[i] != null && invocation.getArguments()[i] instanceof String) { String sparam = (String) invocation.getArguments()[i]; String trim = sparam.trim(); if (trim.isEmpty()) invocation.getArguments()[i] = null; else invocation.getArguments()[i] = trim; } } return invocation.proceed(); } } JUG Milano – Meeting #48 14
  • 15. Demo 2 – Trim parametri (bind) public class GuiceConfig extends GuiceServletContextListener { @Override protected Injector getInjector() { return Guice.createInjector(new JerseyServletModule() { @Override protected void configureServlets() { Map<String, String> params = new HashMap<String, String>(); params.put(PackagesResourceConfig.PROPERTY_PACKAGES, "org.example.demo"); ... filter("/*").through(GuiceContainer.class, params); install(new Module() { public void configure(Binder binder) { LogCall logCall = new LogCall(); TrimAndNullInterceptor trimAndNullableInterceptor = new TrimAndNullInterceptor(); bindInterceptor( Matchers.annotatedWith(Path.class), Matchers.annotatedWith(GET.class).or(Matchers.annotatedWith(POST.class)) .or(Matchers.annotatedWith(PUT.class)).or(Matchers.annotatedWith(DELETE.class)), trimAndNullableInterceptor, logCall); JUG Milano – Meeting #48 15
  • 16. Evitare richieste duplicate Problemi: Ristrasmissioni Doppi submit (anche Tripli...) da browser Timeout lato client che scatena altre prove di richieste Rimedi: Hashtable con chiamate attualmente in corso 429 Too Many Requests (RFC 6585) Infinispan con lock condiviso per sistemi cluster JUG Milano – Meeting #48 16
  • 17. Demo 3 – Richieste duplicate (uso) @POST @UniqueCallOnCluster public Response getAccountBalance(@FormParam("fromuser")... @POST @UniqueCallOnCluster public Response getAccountBalance(@KeyParameter @FormParam("fromuser")... JUG Milano – Meeting #48 17
  • 18. Demo 3 – Richieste duplicate (Inter.) public class UniqueCallOnClusterInterceptor implements MethodInterceptor { ... public Object invoke(MethodInvocation invocation) throws Throwable { String classname = invocation.getMethod().getDeclaringClass().getSimpleName(); String methodName = invocation.getMethod().getName(); String key = classname + "_" + methodName + "_" + extractParameterValue(invocation); TransactionManager tm = keyCallOnClusterService.getTransactionManager(); tm.begin(); boolean success = keyCallOnClusterService.lock(key); if (!success) { logger.info("Non posso effettuare il lock sul cluster per la chiave {}.", key); return Response.status(429).entity("Another call with same parameter is in progress.").build(); } String runningServer = (String) keyCallOnClusterService.get(key); if (runningServer != null) { logger.info("Chiamata già in corso, server {}.", runningServer); return Response.status(429).entity("Another call with same parameter is in progress.").build(); } keyCallOnClusterService.put(key, "todo-hostname"); tm.commit(); ... return invocation.proceed(); ... keyCallOnClusterService.remove(key); } JUG Milano – Meeting #48 18
  • 19. Demo 3 – Richieste duplicate (bind) public class GuiceConfig extends GuiceServletContextListener { @Override protected Injector getInjector() { return Guice.createInjector(new JerseyServletModule() { @Override protected void configureServlets() { Map<String, String> params = new HashMap<String, String>(); params.put(PackagesResourceConfig.PROPERTY_PACKAGES, "org.example.demo"); ... filter("/*").through(GuiceContainer.class, params); install(new Module() { public void configure(Binder binder) { UniqueCallOnClusterInterceptor uniqueCallOnClusterInterceptor = new UniqueCallOnClusterInterceptor(); requestInjection(uniqueCallOnClusterInterceptor); bindInterceptor(Matchers.any(), Matchers.annotatedWith(UniqueCallOnCluster.class), uniqueCallOnClusterInterceptor); JUG Milano – Meeting #48 19
  • 20. Transazioni con AOP JUG Milano – Meeting #48 20
  • 21. Transazioni con AOP JUG Milano – Meeting #48 21
  • 22. Transazioni con AOP JUG Milano – Meeting #48 22
  • 23. Demo 4 – Transazioni (uso) package org.example.demo.controller; @PerRequest @Transactional @Path("services/transactionalresource3") public class TransactionalResource3Write extends AbstractTransactionalResource { @Inject public TransactionalResource3Write() { } @POST @Produces("text/plain") public String get() { ... JUG Milano – Meeting #48 23
  • 24. Demo 4 – Transazioni (uso) package org.example.demo.controller; @PerRequest @Transactional(TransactionType.ReadOnly) @Path("services/transactionalresource1") public class TransactionalResource1ReadOnly extends AbstractTransactionalResource { @Inject public TransactionalResource1ReadOnly() { } @GET @Produces("text/plain") @SuppressWarnings("unchecked") public String get() { List<DatabaseLog> list = getSession().createCriteria(DatabaseLog.class).list(); if (list.size() == 0) return "No record!"; JUG Milano – Meeting #48 24
  • 25. Demo 4 – Transazioni (uso) package org.example.demo.controller; @PerRequest @Transactional(TransactionType.RequiredNew) @Path("services/transactionalresource5") public class TransactionalResource5ReqNew extends AbstractTransactionalResource { @Inject public TransactionalResource5ReqNew() { } ... JUG Milano – Meeting #48 25
  • 26. Demo 4 – Transazioni (uso) public abstract class AbstractTransactionalResource { private Session session; @NoTransactional public void setSession(Session session) { this.session = session; } @NoTransactional public Session getSession() { return session; } @Override @NoTransactional protected void finalize() throws Throwable { super.finalize(); } } JUG Milano – Meeting #48 26
  • 27. Demo 4 – Transazioni 1/2 (interc.) public class TransactionInterceptor implements MethodInterceptor { private final ThreadLocal<Stack<Session>> sessionThreadLocal; public Object invoke(MethodInvocation invocation) throws Throwable { ... Transactional transactional = invocation.getMethod().getDeclaringClass().getAnnotation(Transactional.class); ... Stack<Session> sessionStack = sessionThreadLocal.get(); Transaction transaction = null; Session session = null; if (!sessionStack.isEmpty()) session = sessionStack.peek(); if (session == null || transType.equals(TransactionType.RequiredNew)) { boolean readonly = false; readonly = transType.equals(TransactionType.ReadOnly); session = hibernateSessionService.openSession(readonly); transaction = session.getTransaction(); transaction.begin(); sessionStack.push(session); } Session oldSession = null; AbstractTransactionalResource service = ((AbstractTransactionalResource) invocation.getThis()); oldSession = service.getSession(); service.setSession(session); Object result = invocation.proceed(); JUG Milano – Meeting #48 27
  • 28. Demo 4 – Transazioni 2/2 (interc.) try { Object result = invocation.proceed(); if (transaction != null) { session.flush(); transaction.commit(); } return result; } catch (Exception e) { transaction.rollback(); throw e; } finally { if (transaction != null) { hibernateSessionService.closeSession(session); sessionStack.pop(); if (sessionStack.isEmpty()) sessionThreadLocal.remove(); } service.setSession(oldSession); } } } JUG Milano – Meeting #48 28
  • 29. Demo 4 – Transazioni (bind) public class GuiceConfig extends GuiceServletContextListener { @Override protected Injector getInjector() { return Guice.createInjector(new JerseyServletModule() { @Override protected void configureServlets() { Map<String, String> params = new HashMap<String, String>(); params.put(PackagesResourceConfig.PROPERTY_PACKAGES, "org.example.demo"); ... filter("/*").through(GuiceContainer.class, params); install(new Module() { public void configure(Binder binder) { TransactionInterceptor transactionInterceptor = new TransactionInterceptor(); requestInjection(transactionInterceptor); bindInterceptor(Matchers.annotatedWith(Transactional.class), Matchers.not(Matchers.annotatedWith(NoTransactional.class)), TransactionInterceptor); JUG Milano – Meeting #48 29
  • 30. Demo 5 - Login Cookie (bind) Annotation: AuthenticatedUser ApplicationRolesAllowed Provider: AuthenticatedUserProvider Exception e ExceptionMapper: NotAuthenticatedException(+Mapper) NotAuthorizedException(+Mapper) Cookie: LoginCookieManager Utente: DemoPrincipal Interceptor: ApplicationRolesAllowedInterceptor JUG Milano – Meeting #48 30

Hinweis der Redaktion

  1. Rel 1.1 Goals: POJO-based, HTTP-centric, Format Independence, Container Independence, Inclusion in Java EE. La release 2.0 si focalizza su HATEOAS e implementazioni client, ma anche su Validation, MVC, Async, Filters/Handlers, migliorie al Content Negotiation. Attualmente Early Draft Review 2.
  2. @FormParam is slightly special because it extracts information from a request representation that is of the MIME media type &amp;quot;application/x-www-form-urlencoded&amp;quot;
  3. Listener per la configurazione dell&apos;injector (bind,AOP). Filter per il processing delle richieste.
  4. Il log delle richieste già lo abbiamo sul access log del nostro webserver o application server. Ma per quanto riquarda il body in POST o PUT non ci viene in aiuto. Con questo Interceptor possiamo loggare sul nostro file applicativo le richieste che arrivano con tutti i parametri in input e il THREAD che evade la chiamata
  5. RFC6585: Additional HTTP Status Codes, April 2012, tra le altre cose: 3. 428 Precondition 4. 429 Too Many Requests 5. 431 Request Header Fields Too Large 6. 511 Network Authentication Required
  6. Come si usa