com.aol.micro.server.rest.jersey.AsyncDispatcher Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of micro-jersey Show documentation
Show all versions of micro-jersey Show documentation
Opinionated rest microservices
The newest version!
package com.aol.micro.server.rest.jersey;
import com.aol.cyclops2.types.mixins.Printable;
import cyclops.stream.ReactiveSeq;
import cyclops.stream.Spouts;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import org.glassfish.hk2.api.ServiceHandle;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.jersey.server.ContainerRequest;
import org.glassfish.jersey.server.internal.LocalizationMessages;
import org.glassfish.jersey.server.internal.inject.ConfiguredValidator;
import org.glassfish.jersey.server.internal.process.AsyncContext;
import javax.inject.Provider;
import org.glassfish.jersey.server.model.Invocable;
import org.glassfish.jersey.server.spi.internal.ResourceMethodDispatcher;
import org.reactivestreams.Publisher;
import javax.ws.rs.ProcessingException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import java.lang.reflect.InvocationHandler;
import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;
public class AsyncDispatcher implements ResourceMethodDispatcher {
private final ResourceMethodDispatcher originalDispatcher;
@Context
private javax.inject.Provider asyncContext;
@Context
private javax.inject.Provider containerRequestContext;
public AsyncDispatcher(ResourceMethodDispatcher originalDispatcher) {
this.originalDispatcher = originalDispatcher;
}
@AllArgsConstructor
@NoArgsConstructor
static class AsyncDispatcherProvider implements Provider{
@Context
private ServiceLocator serviceLocator;
@Override
public ResourceMethodDispatcher create(Invocable method, InvocationHandler handler, ConfiguredValidator validator) {
final Class> returnType = method.getHandlingMethod().getReturnType();
if(Publisher.class.isAssignableFrom(returnType) & !Collection.class.isAssignableFrom(returnType)){
Set providers = serviceLocator.getAllServiceHandles(ResourceMethodDispatcher.Provider.class)
.stream()
.filter(h->!h.getActiveDescriptor()
.getImplementationClass()
.equals(AsyncDispatcherProvider.class))
.map(ServiceHandle::getService)
.collect(Collectors.toSet());
for (ResourceMethodDispatcher.Provider provider : providers) {
ResourceMethodDispatcher dispatcher = provider.create(method, handler, validator);
if (dispatcher != null) {
AsyncDispatcher result = new AsyncDispatcher(dispatcher);
serviceLocator.inject(result);
return result;
}
}
}
return null;
}
}
@Override
public Response dispatch(Object resource, ContainerRequest request) throws ProcessingException {
final AsyncContext context = this.asyncContext.get();
if(!context.suspend())
throw new ProcessingException(LocalizationMessages.ERROR_SUSPENDING_ASYNC_REQUEST());
final ContainerRequestContext requestContext = containerRequestContext.get();
Publisher pub = (Publisher)originalDispatcher.dispatch(resource, request)
.getEntity();
Spouts.from(pub).onEmptySwitch(()->Spouts.of(Response.noContent().build()))
.forEach(1,context::resume, context::resume);
return null;
}
}