All Downloads are FREE. Search and download functionalities are using the official Maven repository.

webpiecesxxxxxpackage.json.JsonController Maven / Gradle / Ivy

package webpiecesxxxxxpackage.json;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;

import javax.inject.Inject;
import javax.inject.Singleton;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.webpieces.ctx.api.Current;
import org.webpieces.ctx.api.RequestContext;
import org.webpieces.plugin.json.Jackson;
import org.webpieces.router.api.RouterStreamHandle;
import org.webpieces.router.api.exceptions.NotFoundException;

import com.webpieces.http2.api.dto.highlevel.Http2Response;
import com.webpieces.http2.api.dto.lowlevel.CancelReason;
import com.webpieces.http2.api.dto.lowlevel.DataFrame;
import com.webpieces.http2.api.dto.lowlevel.lib.StreamMsg;
import com.webpieces.http2.api.streaming.ResponseStreamHandle;
import com.webpieces.http2.api.streaming.StreamRef;
import com.webpieces.http2.api.streaming.StreamWriter;

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;

@Singleton
public class JsonController implements ClientApi {
	
	private static final Logger log = LoggerFactory.getLogger(JsonController.class);

	private Counter counter;

	@Inject
	public JsonController(MeterRegistry metrics) {
		counter = metrics.counter("testCounter");
	}
	
	public CompletableFuture asyncJsonRequest(int id, @Jackson SearchRequest request) {
		SearchResponse resp = new SearchResponse();
		resp.setSearchTime(8);
		resp.getMatches().add("match1");
		resp.getMatches().add("match2");
		
		return CompletableFuture.completedFuture(resp);
	}
	
	public SearchResponse jsonRequest(int id, @Jackson SearchRequest request) {
		counter.increment();
		SearchResponse resp = new SearchResponse();
		resp.setSearchTime(5);
		resp.getMatches().add("match1");
		resp.getMatches().add("match2");
		
		return resp;
	}
	
	@Override
	public SearchResponse postJson(@Jackson SearchRequest request) {
		SearchResponse resp = new SearchResponse();
		resp.setSearchTime(99);
		resp.getMatches().add("match1");
		resp.getMatches().add("match2");
		
		return resp;
	}
	
	public CompletableFuture postAsyncJson(int id, @Jackson SearchRequest request) {
		SearchResponse resp = new SearchResponse();
		resp.setSearchTime(98);
		resp.getMatches().add("match1");
		resp.getMatches().add("match2");
		
		return CompletableFuture.completedFuture(resp);
	}
	
	@Jackson
	public SearchResponse readOnly() {
		SearchResponse resp = new SearchResponse();
		resp.setSearchTime(1);
		return resp;
	}
	
	public SearchResponse throwNotFound(int id, @Jackson SearchRequest request) {
		throw new NotFoundException("to test it out");
	}
	
	//Method signature cannot have RequestContext since in microservices, we implement an api as the server
	//AND a client implements the same api AND client does not have a RequestContext!!
	@Override
	public StreamRef myStream(ResponseStreamHandle handle2) {
		RouterStreamHandle handle  = (RouterStreamHandle) handle2;
		RequestContext requestCtx = Current.getContext(); 
		
		Http2Response response = handle.createBaseResponse(requestCtx.getRequest().originalRequest, "text/plain", 200, "Ok");
		response.setEndOfStream(false);
		
		CompletableFuture responseWriter = handle.process(response);
		return new RequestStreamEchoWriter(requestCtx, handle, responseWriter);
	}

	private static class RequestStreamEchoWriter implements StreamWriter, StreamRef {

		private AtomicInteger total = new AtomicInteger();
		private CompletableFuture responseWriter;
		private RouterStreamHandle handle; // in case you want to cancel the request

		public RequestStreamEchoWriter(RequestContext requestCtx, RouterStreamHandle handle,
				CompletableFuture responseWriter2) {
			this.responseWriter = responseWriter2;
			this.handle = handle;
		}

		@Override
		public CompletableFuture processPiece(StreamMsg data) {
			RequestContext requestCtx = Current.getContext(); 

			DataFrame f = (DataFrame) data;
			int numReceived = total.addAndGet(f.getData().getReadableSize());
			log.info("Num bytes received so far="+numReceived+" for requests="+requestCtx.getRequest().relativePath);
			
			if(data.isEndOfStream()) {
				log.info("Upload complete");
				return responseWriter.thenCompose(w -> w.processPiece(data));
			}

			//We just echo data back to whatever the client sent as the client sends it...
			return responseWriter.thenCompose(w -> w.processPiece(data));
		}

		@Override
		public CompletableFuture getWriter() {
			//let's make it wait for our response to be written by 
			//chaining with responseWriter future here
			return responseWriter.thenApply(s -> this);
		}

		@Override
		public CompletableFuture cancel(CancelReason reason) {
			//here if using http client, we may forward to next stream like so
			//responseStream.cancel(reason);
			//but since the responseStream and request is the same, we can just stop sending instead
			//which happens automatically since they stopped sending(ie. nothing to do here
			return CompletableFuture.completedFuture(null);
		}

	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy