/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 2013-2017 Oracle and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can * obtain a copy of the License at * http://glassfish.java.net/public/CDDL+GPL_1_1.html * or packager/legal/LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at packager/legal/LICENSE.txt. * * GPL Classpath Exception: * Oracle designates this particular file as subject to the "Classpath" * exception as provided by Oracle in the GPL Version 2 section of the License * file that accompanied this code. * * Modifications: * If applicable, add the following below the License Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyright [year] [name of copyright owner]" * * Contributor(s): * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don't indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. */ package org.glassfish.jersey.tests.e2e.server.monitoring; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.client.Entity; import javax.ws.rs.container.AsyncResponse; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.container.ContainerResponseContext; import javax.ws.rs.container.ContainerResponseFilter; import javax.ws.rs.container.PreMatching; import javax.ws.rs.container.Suspended; import javax.ws.rs.core.Application; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedHashMap; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import org.glassfish.jersey.server.ManagedAsync; import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.server.model.ResourceMethod; import org.glassfish.jersey.server.monitoring.ApplicationEvent; import org.glassfish.jersey.server.monitoring.ApplicationEventListener; import org.glassfish.jersey.server.monitoring.RequestEvent; import org.glassfish.jersey.server.monitoring.RequestEventListener; import org.glassfish.jersey.test.JerseyTest; import org.junit.Assert; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; /** * @author Miroslav Fuksa */ public class EventListenerTest extends JerseyTest { private static final String APPLICATION_NAME = "MyApplication"; private static AppEventListener applicationEventListener; @Override protected Application configure() { applicationEventListener = new AppEventListener(); final ResourceConfig resourceConfig = new ResourceConfig(MyResource.class); resourceConfig.register(applicationEventListener); resourceConfig.register(RequestFilter.class); resourceConfig.register(PreMatchingRequestFilter.class); resourceConfig.register(ResponseFilter.class); resourceConfig.register(MyExceptionMapper.class); resourceConfig.setApplicationName(APPLICATION_NAME); return resourceConfig; } public static class AppEventListener implements ApplicationEventListener { private ApplicationEvent appEventInitStart; private ApplicationEvent appEventInitFinished; private RequestEvent newRequestEvent; private volatile int resourceMethodEventCount = 0; private volatile CountDownLatch finishedCalled = new CountDownLatch(1); @Override public void onEvent(ApplicationEvent event) { switch (event.getType()) { case INITIALIZATION_START: this.appEventInitStart = event; break; case INITIALIZATION_APP_FINISHED: this.appEventInitFinished = event; break; } } @Override public RequestEventListener onRequest(RequestEvent newRequestEvent) { this.newRequestEvent = newRequestEvent; if ("POST".equals(newRequestEvent.getContainerRequest().getMethod())) { return null; } return new ReqEventListener(this); } } public static class ReqEventListener implements RequestEventListener { private final AppEventListener appEventListener; public final MultivaluedMap<String, String> eventData = new MultivaluedHashMap<String, String>(); public ReqEventListener(AppEventListener appEventListener) { this.appEventListener = appEventListener; } private int index = 1; @Override public void onEvent(RequestEvent event) { switch (event.getType()) { case REQUEST_MATCHED: eventData.add("R.REQ_FILTERS_START.order", String.valueOf(index++)); break; case REQUEST_FILTERED: eventData.add("R.REQ_FILTERS_FINISHED.order", String.valueOf(index++)); break; case LOCATOR_MATCHED: eventData.add("R.MATCHED_LOCATOR.order", String.valueOf(index++)); final List<ResourceMethod> locators = event.getUriInfo().getMatchedResourceLocators(); String msg = String.valueOf(locators.size()) + ":" + locators.get(0).getInvocable().getHandlingMethod().getName(); eventData.add("R.MATCHED_LOCATOR", msg); break; case SUBRESOURCE_LOCATED: eventData.add("R.MATCHED_SUB_RESOURCE.order", String.valueOf(index++)); break; case RESOURCE_METHOD_START: eventData.add("R.RESOURCE_METHOD_START.order", String.valueOf(index++)); this.appEventListener.resourceMethodEventCount++; final ResourceMethod resourceMethod = event.getUriInfo().getMatchedResourceMethod(); eventData.add("R.RESOURCE_METHOD_START.method", resourceMethod .getInvocable().getHandlingMethod().getName()); break; case RESOURCE_METHOD_FINISHED: eventData.add("R.RESOURCE_METHOD_FINISHED.order", String.valueOf(index++)); eventData.add("R.RESOURCE_METHOD_FINISHED", "ok"); break; case RESP_FILTERS_START: eventData.add("R.RESP_FILTERS_START.order", String.valueOf(index++)); break; case EXCEPTION_MAPPER_FOUND: eventData.add("R.EXCEPTION_MAPPER_FOUND.order", String.valueOf(index++)); eventData.add("R.EXCEPTION_MAPPER_FOUND.exception", event.getException().getMessage()); break; case RESP_FILTERS_FINISHED: eventData.add("R.RESP_FILTERS_FINISHED.order", String.valueOf(index++)); for (Map.Entry<String, List<String>> entry : eventData.entrySet()) { event.getContainerResponse().getHeaders().addAll(entry.getKey(), entry.getValue()); } break; case FINISHED: Assert.assertNotNull(event.getContainerResponse()); this.appEventListener.finishedCalled.countDown(); break; } } } public static class MyMappableException extends RuntimeException { public MyMappableException(String message) { super(message); } } public static class MyExceptionMapper implements ExceptionMapper<MyMappableException> { @Override public Response toResponse(MyMappableException exception) { return Response.ok("mapped").build(); } } public static class RequestFilter implements ContainerRequestFilter { @Override public void filter(ContainerRequestContext requestContext) throws IOException { } } @PreMatching public static class PreMatchingRequestFilter implements ContainerRequestFilter { @Override public void filter(ContainerRequestContext requestContext) throws IOException { } } public static class ResponseFilter implements ContainerResponseFilter { @Override public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException { } } @Path("resource") public static class MyResource { @GET public String getMethod() { return "get"; } @POST public void post(String entity) { } @Path("locator") public SubResource locator() { return new SubResource(); } @GET @Path("async") @ManagedAsync public void getAsync(@Suspended AsyncResponse asyncResponse) { asyncResponse.resume(Response.ok("async").build()); } /** * This works in the async way but it is served by only one thread. * @param asyncResponse */ @GET @Path("asyncOneThread") public void getAsyncOneThread(@Suspended AsyncResponse asyncResponse) { asyncResponse.resume(Response.ok("async").build()); } } public static class SubResource { @GET public String get() { return "sub"; } @GET @Path("exception") public String getException() { throw new MyMappableException("test-error"); } } @Test public void testApplicationEvents() { assertNotNull(applicationEventListener.appEventInitStart); assertNotNull(applicationEventListener.appEventInitFinished); assertEquals(APPLICATION_NAME, applicationEventListener.appEventInitStart.getResourceConfig().getApplicationName()); assertNull(applicationEventListener.newRequestEvent); final Response response = target().path("resource").request().get(); assertEquals(200, response.getStatus()); assertNotNull(applicationEventListener.newRequestEvent); } @Test public void testSimpleRequestEvent() { assertEquals(0, applicationEventListener.resourceMethodEventCount); assertNotNull(applicationEventListener.appEventInitStart); assertNull(applicationEventListener.newRequestEvent); Response response = target().path("resource").request().post(Entity.entity("entity", MediaType.TEXT_PLAIN_TYPE)); assertEquals(204, response.getStatus()); assertNotNull(applicationEventListener.newRequestEvent); assertEquals(0, applicationEventListener.resourceMethodEventCount); response = target().path("resource").request().get(); assertEquals(200, response.getStatus()); assertEquals(1, applicationEventListener.resourceMethodEventCount); } @Test public void testMatchedLocator() { final Response response = target().path("resource/locator").request().get(); assertEquals(200, response.getStatus()); assertEquals("sub", response.readEntity(String.class)); assertEquals("[1:locator]", response.getHeaderString("R.MATCHED_LOCATOR")); } @Test public void testMatchedMethod() { final Response response = target().path("resource").request().get(); assertEquals(200, response.getStatus()); assertEquals("get", response.readEntity(String.class)); assertEquals("[getMethod]", response.getHeaderString("R.RESOURCE_METHOD_START.method")); assertEquals("[ok]", response.getHeaderString("R.RESOURCE_METHOD_FINISHED")); } @Test public void testException() { final Response response = target().path("resource/locator/exception").request().get(); assertEquals(200, response.getStatus()); assertEquals("mapped", response.readEntity(String.class)); assertEquals("[org.glassfish.jersey.tests.e2e.server.monitoring.EventListenerTest$MyMappableException: test-error]", response.getHeaderString("R.EXCEPTION_MAPPER_FOUND.exception")); } @Test public void testSimpleProcessing() { final Response response = target().path("resource").request().get(); assertEquals(200, response.getStatus()); assertEquals("get", response.readEntity(String.class)); int i = 1; System.out.println(response.getHeaders()); assertEquals("[" + i++ + "]", response.getHeaderString("R.REQ_FILTERS_START.order")); assertEquals("[" + i++ + "]", response.getHeaderString("R.REQ_FILTERS_FINISHED.order")); assertEquals("[" + i++ + "]", response.getHeaderString("R.RESOURCE_METHOD_START.order")); assertEquals("[" + i++ + "]", response.getHeaderString("R.RESOURCE_METHOD_FINISHED.order")); assertEquals("[" + i++ + "]", response.getHeaderString("R.RESP_FILTERS_START.order")); assertEquals("[" + i + "]", response.getHeaderString("R.RESP_FILTERS_FINISHED.order")); } @Test public void testLocatorProcessing() { final Response response = target().path("resource/locator").request().get(); assertEquals(200, response.getStatus()); assertEquals("sub", response.readEntity(String.class)); int i = 1; System.out.println(response.getHeaders()); assertEquals("[" + i++ + "]", response.getHeaderString("R.MATCHED_LOCATOR.order")); assertEquals("[" + i++ + "]", response.getHeaderString("R.MATCHED_SUB_RESOURCE.order")); assertEquals("[" + i++ + "]", response.getHeaderString("R.REQ_FILTERS_START.order")); assertEquals("[" + i++ + "]", response.getHeaderString("R.REQ_FILTERS_FINISHED.order")); assertEquals("[" + i++ + "]", response.getHeaderString("R.RESOURCE_METHOD_START.order")); assertEquals("[" + i++ + "]", response.getHeaderString("R.RESOURCE_METHOD_FINISHED.order")); assertEquals("[" + i++ + "]", response.getHeaderString("R.RESP_FILTERS_START.order")); assertEquals("[" + i + "]", response.getHeaderString("R.RESP_FILTERS_FINISHED.order")); } @Test public void testExceptionProcessing() { final Response response = target().path("resource/locator/exception").request().get(); assertEquals(200, response.getStatus()); assertEquals("mapped", response.readEntity(String.class)); int i = 1; System.out.println(response.getHeaders()); assertEquals("[" + i++ + "]", response.getHeaderString("R.MATCHED_LOCATOR.order")); assertEquals("[" + i++ + "]", response.getHeaderString("R.MATCHED_SUB_RESOURCE.order")); assertEquals("[" + i++ + "]", response.getHeaderString("R.REQ_FILTERS_START.order")); assertEquals("[" + i++ + "]", response.getHeaderString("R.REQ_FILTERS_FINISHED.order")); assertEquals("[" + i++ + "]", response.getHeaderString("R.RESOURCE_METHOD_START.order")); assertEquals("[" + i++ + "]", response.getHeaderString("R.RESOURCE_METHOD_FINISHED.order")); assertEquals("[" + i++ + "]", response.getHeaderString("R.EXCEPTION_MAPPER_FOUND.order")); assertEquals("[" + i++ + "]", response.getHeaderString("R.RESP_FILTERS_START.order")); assertEquals("[" + i + "]", response.getHeaderString("R.RESP_FILTERS_FINISHED.order")); } @Test public void testAsyncProcessing() throws InterruptedException { final Response response = target().path("resource/async").request().get(); assertEquals(200, response.getStatus()); assertEquals("async", response.readEntity(String.class)); int i = 1; System.out.println(response.getHeaders()); assertEquals("[" + i++ + "]", response.getHeaderString("R.REQ_FILTERS_START.order")); assertEquals("[" + i++ + "]", response.getHeaderString("R.REQ_FILTERS_FINISHED.order")); assertEquals("[" + i++ + "]", response.getHeaderString("R.RESOURCE_METHOD_START.order")); assertEquals("[" + i++ + "]", response.getHeaderString("R.RESP_FILTERS_START.order")); assertEquals("[" + i + "]", response.getHeaderString("R.RESP_FILTERS_FINISHED.order")); final boolean success = applicationEventListener.finishedCalled.await(3 * getAsyncTimeoutMultiplier(), TimeUnit.SECONDS); Assert.assertTrue(success); } @Test public void testAsyncProcessingWithOneThread() throws InterruptedException { final Response response = target().path("resource/asyncOneThread").request().get(); assertEquals(200, response.getStatus()); assertEquals("async", response.readEntity(String.class)); int i = 1; System.out.println(response.getHeaders()); assertEquals("[" + i++ + "]", response.getHeaderString("R.REQ_FILTERS_START.order")); assertEquals("[" + i++ + "]", response.getHeaderString("R.REQ_FILTERS_FINISHED.order")); assertEquals("[" + i++ + "]", response.getHeaderString("R.RESOURCE_METHOD_START.order")); assertEquals("[" + i++ + "]", response.getHeaderString("R.RESP_FILTERS_START.order")); assertEquals("[" + i + "]", response.getHeaderString("R.RESP_FILTERS_FINISHED.order")); final boolean success = applicationEventListener.finishedCalled.await(3 * getAsyncTimeoutMultiplier(), TimeUnit.SECONDS); Assert.assertTrue(success); } }