SlideShare a Scribd company logo
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

More Related Content

What's hot (20)

PDF
Guice2.0
Masaaki Yonebayashi
 
PDF
Слава Бобик «NancyFx для самых маленьких»
SpbDotNet Community
 
PDF
Advanced Java Practical File
Soumya Behera
 
PDF
京都Gtugコンパチapi
Masafumi Terazono
 
PDF
망고100 보드로 놀아보자 19
종인 전
 
PDF
Spock and Geb in Action
Christian Baranowski
 
PPTX
Java practice programs for beginners
ishan0019
 
PDF
The Ring programming language version 1.5.3 book - Part 78 of 184
Mahmoud Samir Fayed
 
PPTX
What’s new in C# 6
Fiyaz Hasan
 
PPTX
#5 (Remote Method Invocation)
Ghadeer AlHasan
 
PDF
Dagger & rxjava & retrofit
Ted Liang
 
PDF
Bang-Bang, you have been hacked - Yonatan Levin, KolGene
DroidConTLV
 
PDF
The Ring programming language version 1.10 book - Part 94 of 212
Mahmoud Samir Fayed
 
PDF
The Ring programming language version 1.8 book - Part 95 of 202
Mahmoud Samir Fayed
 
PDF
The Ring programming language version 1.5.2 book - Part 13 of 181
Mahmoud Samir Fayed
 
PDF
Java 7 at SoftShake 2011
julien.ponge
 
PDF
Current State of Coroutines
Guido Pio Mariotti
 
PDF
Java 7 JUG Summer Camp
julien.ponge
 
PPTX
Java весна 2013 лекция 2
Technopark
 
PDF
Software Testing - Invited Lecture at UNSW Sydney
julien.ponge
 
Слава Бобик «NancyFx для самых маленьких»
SpbDotNet Community
 
Advanced Java Practical File
Soumya Behera
 
京都Gtugコンパチapi
Masafumi Terazono
 
망고100 보드로 놀아보자 19
종인 전
 
Spock and Geb in Action
Christian Baranowski
 
Java practice programs for beginners
ishan0019
 
The Ring programming language version 1.5.3 book - Part 78 of 184
Mahmoud Samir Fayed
 
What’s new in C# 6
Fiyaz Hasan
 
#5 (Remote Method Invocation)
Ghadeer AlHasan
 
Dagger & rxjava & retrofit
Ted Liang
 
Bang-Bang, you have been hacked - Yonatan Levin, KolGene
DroidConTLV
 
The Ring programming language version 1.10 book - Part 94 of 212
Mahmoud Samir Fayed
 
The Ring programming language version 1.8 book - Part 95 of 202
Mahmoud Samir Fayed
 
The Ring programming language version 1.5.2 book - Part 13 of 181
Mahmoud Samir Fayed
 
Java 7 at SoftShake 2011
julien.ponge
 
Current State of Coroutines
Guido Pio Mariotti
 
Java 7 JUG Summer Camp
julien.ponge
 
Java весна 2013 лекция 2
Technopark
 
Software Testing - Invited Lecture at UNSW Sydney
julien.ponge
 

Similar to Jersey Guice AOP (20)

PPT
比XML更好用的Java Annotation
javatwo2011
 
ODP
Codemotion appengine
Ignacio Coloma
 
PPTX
Anti patterns
Alex Tumanoff
 
PDF
Google App Engine Developer - Day3
Simon Su
 
PDF
Fun Teaching MongoDB New Tricks
MongoDB
 
PDF
JJUG CCC 2011 Spring
Kiyotaka Oku
 
KEY
Android workshop
Michael Galpin
 
PDF
Clean coding-practices
John Ferguson Smart Limited
 
PPT
E:\Plp 2009 2\Plp 9
Ismar Silveira
 
PPT
Paradigmas de linguagens de programacao - aula#9
Ismar Silveira
 
PDF
Ten useful JavaScript tips & best practices
Ankit Rastogi
 
PDF
Testing in android
jtrindade
 
PPTX
Jdk 7 4-forkjoin
knight1128
 
PDF
名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン
Tsuyoshi Yamamoto
 
PDF
Struts2 notes
Rajiv Gupta
 
PDF
服务框架: Thrift & PasteScript
Qiangning Hong
 
PPTX
Introduccion a AspectJ
Mauricio Quezada
 
PDF
Overview of Android Infrastructure
Alexey Buzdin
 
PDF
Overview of Android Infrastructure
C.T.Co
 
DOCX
Diifeerences In C#
rohit_gupta_mrt
 
比XML更好用的Java Annotation
javatwo2011
 
Codemotion appengine
Ignacio Coloma
 
Anti patterns
Alex Tumanoff
 
Google App Engine Developer - Day3
Simon Su
 
Fun Teaching MongoDB New Tricks
MongoDB
 
JJUG CCC 2011 Spring
Kiyotaka Oku
 
Android workshop
Michael Galpin
 
Clean coding-practices
John Ferguson Smart Limited
 
E:\Plp 2009 2\Plp 9
Ismar Silveira
 
Paradigmas de linguagens de programacao - aula#9
Ismar Silveira
 
Ten useful JavaScript tips & best practices
Ankit Rastogi
 
Testing in android
jtrindade
 
Jdk 7 4-forkjoin
knight1128
 
名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン
Tsuyoshi Yamamoto
 
Struts2 notes
Rajiv Gupta
 
服务框架: Thrift & PasteScript
Qiangning Hong
 
Introduccion a AspectJ
Mauricio Quezada
 
Overview of Android Infrastructure
Alexey Buzdin
 
Overview of Android Infrastructure
C.T.Co
 
Diifeerences In C#
rohit_gupta_mrt
 
Ad

More from Domenico Briganti (8)

PDF
Software Testing e TDD
Domenico Briganti
 
ODP
XML Schema (XSD)
Domenico Briganti
 
PPT
Xml annessi e connessi
Domenico Briganti
 
PPT
Java codestyle & tipstricks
Domenico Briganti
 
ODP
Testing
Domenico Briganti
 
PPT
Xml Xslt
Domenico Briganti
 
Software Testing e TDD
Domenico Briganti
 
XML Schema (XSD)
Domenico Briganti
 
Xml annessi e connessi
Domenico Briganti
 
Java codestyle & tipstricks
Domenico Briganti
 
Ad

Recently uploaded (20)

PDF
RAT Builders - How to Catch Them All [DeepSec 2024]
malmoeb
 
PPTX
AVL ( audio, visuals or led ), technology.
Rajeshwri Panchal
 
PDF
Economic Impact of Data Centres to the Malaysian Economy
flintglobalapac
 
PDF
TrustArc Webinar - Navigating Data Privacy in LATAM: Laws, Trends, and Compli...
TrustArc
 
PDF
Researching The Best Chat SDK Providers in 2025
Ray Fields
 
PDF
MASTERDECK GRAPHSUMMIT SYDNEY (Public).pdf
Neo4j
 
PPTX
OA presentation.pptx OA presentation.pptx
pateldhruv002338
 
PDF
Make GenAI investments go further with the Dell AI Factory
Principled Technologies
 
PPTX
Simple and concise overview about Quantum computing..pptx
mughal641
 
PPTX
cloud computing vai.pptx for the project
vaibhavdobariyal79
 
PPTX
AI in Daily Life: How Artificial Intelligence Helps Us Every Day
vanshrpatil7
 
PPTX
IT Runs Better with ThousandEyes AI-driven Assurance
ThousandEyes
 
PDF
Data_Analytics_vs_Data_Science_vs_BI_by_CA_Suvidha_Chaplot.pdf
CA Suvidha Chaplot
 
PDF
Trying to figure out MCP by actually building an app from scratch with open s...
Julien SIMON
 
PDF
Presentation about Hardware and Software in Computer
snehamodhawadiya
 
PDF
NewMind AI Weekly Chronicles – July’25, Week III
NewMind AI
 
PPTX
AI Code Generation Risks (Ramkumar Dilli, CIO, Myridius)
Priyanka Aash
 
PPTX
AI and Robotics for Human Well-being.pptx
JAYMIN SUTHAR
 
PDF
introduction to computer hardware and sofeware
chauhanshraddha2007
 
PDF
Brief History of Internet - Early Days of Internet
sutharharshit158
 
RAT Builders - How to Catch Them All [DeepSec 2024]
malmoeb
 
AVL ( audio, visuals or led ), technology.
Rajeshwri Panchal
 
Economic Impact of Data Centres to the Malaysian Economy
flintglobalapac
 
TrustArc Webinar - Navigating Data Privacy in LATAM: Laws, Trends, and Compli...
TrustArc
 
Researching The Best Chat SDK Providers in 2025
Ray Fields
 
MASTERDECK GRAPHSUMMIT SYDNEY (Public).pdf
Neo4j
 
OA presentation.pptx OA presentation.pptx
pateldhruv002338
 
Make GenAI investments go further with the Dell AI Factory
Principled Technologies
 
Simple and concise overview about Quantum computing..pptx
mughal641
 
cloud computing vai.pptx for the project
vaibhavdobariyal79
 
AI in Daily Life: How Artificial Intelligence Helps Us Every Day
vanshrpatil7
 
IT Runs Better with ThousandEyes AI-driven Assurance
ThousandEyes
 
Data_Analytics_vs_Data_Science_vs_BI_by_CA_Suvidha_Chaplot.pdf
CA Suvidha Chaplot
 
Trying to figure out MCP by actually building an app from scratch with open s...
Julien SIMON
 
Presentation about Hardware and Software in Computer
snehamodhawadiya
 
NewMind AI Weekly Chronicles – July’25, Week III
NewMind AI
 
AI Code Generation Risks (Ramkumar Dilli, CIO, Myridius)
Priyanka Aash
 
AI and Robotics for Human Well-being.pptx
JAYMIN SUTHAR
 
introduction to computer hardware and sofeware
chauhanshraddha2007
 
Brief History of Internet - Early Days of Internet
sutharharshit158
 

Jersey Guice AOP

  • 1. Jersey + Guice + AOP Domenico Briganti [email protected]
  • 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("[email protected]"); 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

Editor's Notes

  • #5: 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.
  • #8: @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;
  • #11: Listener per la configurazione dell&apos;injector (bind,AOP). Filter per il processing delle richieste.
  • #13: 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
  • #17: 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
  • #18: Come si usa