Your SlideShare is downloading. ×
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Jersey Guice AOP
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Jersey Guice AOP

988

Published on

Poche chiacchiere e tanto codice per cercare rendere la nostra vita di …

Poche chiacchiere e tanto codice per cercare rendere la nostra vita di
sviluppatori più divertente.
Parleremo di JAX-RS, le annotazioni, l'MVC che mette a disposizione e
l'integrazione di Jersey con Guice.
Useremo AOP per gestire log, transazioni e con l'aiuto di Infinispan
limiteremo le chamate concorrenti sul nostro cluster.

Published in: Technology, Business
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
988
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
22
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide
  • 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.
  • @FormParam is slightly special because it extracts information from a request representation that is of the MIME media type "application/x-www-form-urlencoded"
  • Listener per la configurazione dell'injector (bind,AOP). Filter per il processing delle richieste.
  • 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
  • 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
  • Come si usa
  • Transcript

    • 1. Jersey + Guice + AOP Domenico Briganti dometec@gmail.com
    • 2. Chi sono?@PerRequestpublic 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. AgendaJAX-RSJersey con Guice/AOPDemos:Log delle richiesteTrim dei parametri Stringa in ingressoEvitare chiamate identiche su un clusterTransazioniLogin cookie JUG Milano – Meeting #48 3
    • 4. JAX-RSJava API for RESTful Web ServicesRelease 1.1, JSR 311, 2009, JEE6 FullRelease futura 2.0, JSR 339, (EDR2 2012), JEE7Package: javax.ws.restImplementazioni: Jersey (RI), Apache CXF, RESTEasy, Apache Wink JUG Milano – Meeting #48 4
    • 5. JerseyOpen source, RI for JAX-RSJersey 1.x (1.13b1) implements JAX-RS 1.1Jersey 2.x (mileston 3) implements JAX-RS 2CDDL + GPL 1.1 JUG Milano – Meeting #48 5
    • 6. Jersey Hello Worldimport 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 AnnotationVerbi HTTP: @GET, @POST, @PUT, @DELETE, @OPTION, @HEADIdentificazione risorse: @PathInput: @PathParam, @QueryParam, @MatrixParam, @HeaderParam, @CookieParam. @FormParam. @DefaultValue. MultivaluedMap<String, String>Content negotiation: @Produces, @Consume JUG Milano – Meeting #48 7
    • 8. JAX-RS Annotation e FacilityAmbiente: @Context (ServletConfig, ServletContext, HttpServletRequest, HttpServletResponse, SecurityContext, UriInfo, HttpHeaders)Mapper, MessageBodyWriters, MessageBodyReaders: @ProviderResponseBuilder e UriBuilder JUG Milano – Meeting #48 8
    • 9. DEMO 0 “Esecuzione” dellaslide 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 { @Overridelistener 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 1Log 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 duplicateProblemi: Ristrasmissioni Doppi submit (anche Tripli...) da browser Timeout lato client che scatena altre prove di richiesteRimedi: 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@UniqueCallOnClusterpublic Response getAccountBalance(@FormParam("fromuser")...@POST@UniqueCallOnClusterpublic 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 ApplicationRolesAllowedProvider: AuthenticatedUserProviderException e ExceptionMapper: NotAuthenticatedException(+Mapper) NotAuthorizedException(+Mapper)Cookie: LoginCookieManagerUtente: DemoPrincipalInterceptor: ApplicationRolesAllowedInterceptor JUG Milano – Meeting #48 30
    • 31. Grazie!Domande??Riferimenti:http://jersey.java.nethttp://code.google.com/p/google-guice/Demo webapp: https://github.com/dometec/shadedcode/tree/master/demo-webapp JUG Milano – Meeting #48 31

    ×