use of org.webpieces.util.futures.XFuture in project webpieces by deanhiller.
the class HttpSocketImpl method send.
@Override
public XFuture<HttpFullResponse> send(HttpFullRequest request) {
Integer contentLength = request.getRequest().getContentLength();
if (request.getData() == null || request.getData().getReadableSize() == 0) {
if (contentLength != null && contentLength != 0)
throw new IllegalArgumentException("HttpRequest has 0 Content-Length but readable size=" + request.getData().getReadableSize());
} else if (!request.getRequest().isHasNonZeroContentLength())
throw new IllegalArgumentException("HttpRequest must have Content-Length header");
else if (request.getRequest().getContentLength() != request.getData().getReadableSize())
throw new IllegalArgumentException("HttpRequest Content-Length header value=" + request.getRequest().getContentLength() + " does not match payload size=" + request.getData().getReadableSize());
XFuture<HttpFullResponse> future = new XFuture<HttpFullResponse>();
HttpResponseListener l = new CompletableListener(future);
HttpStreamRef streamRef = send(request.getRequest(), l);
if (request.getData() != null && request.getData().getReadableSize() > 0) {
HttpData data = new HttpData(request.getData(), true);
streamRef.getWriter().thenCompose(w -> {
return w.send(data);
});
}
future.exceptionally(t -> {
// we can only cancel if it is NOT keepalive or else we have to keep socket open
if (t instanceof CancellationException && !isKeepAliveRequest(request.getRequest())) {
streamRef.cancel("XFuture cancelled by client, so cancel request");
}
return null;
});
return future;
}
use of org.webpieces.util.futures.XFuture in project webpieces by deanhiller.
the class TestProdRouter method testAsyncRouteAndMocking.
/**
* This test won't work in DevRoute right now as we need to do the following
* 1. create CompileOnDemand very early on
* 2. do a Thread.current().setContextClassLoader(compileOnDemand.getLatestClassloader())
*
* and this all needs to be done BEFORE TestModule is created and more importantly before
* the bind(SomeService.class) as SomeService will be loaded from one classloader and then
* when DEVrouter creates the controller, the compileOnDemand classloader is used resulting
* in a mismatch.
*/
@Test
public void testAsyncRouteAndMocking() {
Http2Request req = RequestCreation.createHttpRequest(HttpMethod.GET, "/async");
// setup returning a response
XFuture<Integer> future1 = new XFuture<Integer>();
overrides.mockService.addToReturn(future1);
MockStreamHandle mockStream = new MockStreamHandle();
StreamRef ref = server.incomingRequest(req, mockStream);
XFuture<StreamWriter> future = ref.getWriter();
Assert.assertFalse(future.isDone());
// no response yet...
Assert.assertNull(mockStream.getLastResponse());
// release controlleer
int id = 78888;
future1.complete(id);
Assert.assertTrue(future.isDone() && !future.isCompletedExceptionally());
Http2Response resp = mockStream.getLastResponse();
Assert.assertNull(resp.getSingleHeaderValue(Http2HeaderName.AUTHORITY));
Assert.assertEquals("http://" + req.getAuthority() + "/meeting/" + id, resp.getSingleHeaderValue(Http2HeaderName.LOCATION));
// We did not send a keep alive so it should close
Assert.assertTrue(mockStream.isWasClosed());
}
use of org.webpieces.util.futures.XFuture in project webpieces by deanhiller.
the class JsonController method streaming.
public StreamRef streaming(ResponseStreamHandle handle) {
XFuture<StreamRef> futureStream = new XFuture<>();
XFuture<Boolean> authFuture = svc.authenticate("bobsmith");
XFuture<StreamWriter> writer = authFuture.thenCompose(resp -> {
StreamRef streamRef = client.stream(handle);
futureStream.complete(streamRef);
return streamRef.getWriter();
});
return new StreamRefProxy(writer, futureStream);
}
use of org.webpieces.util.futures.XFuture in project webpieces by deanhiller.
the class TestLesson2Html method testAsyncControllerAndRemoteSystem.
/**
* It is highly suggested you step through this test in debug mode to understand the description below...
*
* This is a single threaded test that actually allows the webserver thread to return back to the test before
* the response comes. (in production the thread would process other requests while waiting for remote system response).
* Then the test simulates the response coming in from remote system and makes sure we send a response back
* to the ResponseSender. In implementations like this with a remote system, one can avoid holding threads up
* and allow them to keep working while waiting for a response from the remote system.
*/
@Test
public void testAsyncControllerAndRemoteSystem() {
XFuture<FetchValueResponse> future = new XFuture<FetchValueResponse>();
mockRemote.addValueToReturn(future);
HttpFullRequest req = createRequest("/async");
XFuture<HttpFullResponse> respFuture = http11Socket.send(req);
Assert.assertFalse(respFuture.isDone());
// notice that the thread returned but there is no response back to browser yet such that thread can do more work.
// next, simulate remote system returning a value..
int value = 85;
future.complete(new FetchValueResponse(85));
ResponseWrapper response = ResponseExtract.waitResponseAndWrap(respFuture);
response.assertStatusCode(KnownStatusCode.HTTP_200_OK);
response.assertContains("This is a page with value=" + value);
}
use of org.webpieces.util.futures.XFuture in project webpieces by deanhiller.
the class DtoLookup method find.
@SuppressWarnings("unchecked")
@Override
public <T> XFuture<T> find(Meta paramMeta, ParamTreeNode tree, Function<Class<T>, T> beanCreate) {
if (!(paramMeta instanceof ParamMeta))
throw new UnsupportedOperationException("this plugin does not support type=" + paramMeta.getClass());
ParamMeta m = (ParamMeta) paramMeta;
Class<T> paramTypeToCreate = (Class<T>) m.getFieldClass();
Dto annotation = paramTypeToCreate.getAnnotation(Dto.class);
// EntityManager entityManager = Em.get();
// Metamodel metamodel = entityManager.getMetamodel();
// ManagedType<T> managedType = metamodel.managedType(paramTypeToCreate);
// IdentifiableType<T> entityType = (IdentifiableType<T>) managedType;
Method method;
try {
method = paramTypeToCreate.getMethod("getId");
} catch (NoSuchMethodException | SecurityException e) {
throw new IllegalStateException("Class=" + paramTypeToCreate.getName() + " has an annotation @Dto and this requires that dto to have a method getId, but we could not find that method", e);
}
Class<?> idClazz = method.getReturnType();
// SingularAttribute<? super T, ?> idAttribute = entityType.getId(idClazz);
// String name = idAttribute.getName();
String name = "id";
ParamNode paramNode = tree.get(name);
String value = null;
if (paramNode != null) {
if (!(paramNode instanceof ValueNode))
throw new IllegalStateException("The id field in the DTO should have matched to a " + "ValueNode on incoming data and did not. node=" + paramNode + ". bad multipart form? (Please " + "let us know so we can pair with you on this and I can add better error messaging)");
ValueNode node = (ValueNode) paramNode;
value = node.getValue();
}
if (value == null) {
T theBean = beanCreate.apply(paramTypeToCreate);
return XFuture.completedFuture(theBean);
}
@SuppressWarnings("rawtypes") ObjectStringConverter unmarshaller = translator.getConverter(idClazz);
Object id = unmarshaller.stringToObject(value);
Class lookupClass = annotation.lookupClass();
String function = annotation.function();
Object instance = webInjector.getCurrentInjector().getInstance(lookupClass);
Method lookupMethod;
try {
lookupMethod = lookupClass.getMethod(function, idClazz);
} catch (NoSuchMethodException | SecurityException e) {
throw new IllegalArgumentException("Your function in @Dto='XFuture<" + paramTypeToCreate + "> " + function + "(" + idClazz.getName() + ")' on class=" + lookupClass.getName() + " cannot be found. We also did not find method='" + paramTypeToCreate + " " + function + "(" + idClazz.getName() + ")'");
}
Object result;
try {
result = lookupMethod.invoke(instance, id);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new RuntimeException("Exception invoking lookup method", e);
}
if (result instanceof XFuture) {
return (XFuture<T>) result;
}
return (XFuture<T>) XFuture.completedFuture(result);
}
Aggregations