SlideShare une entreprise Scribd logo
1  sur  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

Contenu connexe

Tendances

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
 

Tendances (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
 

Similaire à 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
 

Similaire à 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#
 

Plus de 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
 

Dernier

Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 

Dernier (20)

Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdf
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
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
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 

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

Notes de l'éditeur

  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