use of com.linkedin.restli.server.RestLiServiceException in project rest.li by linkedin.
the class RestLiMethodInvoker method doInvoke.
@SuppressWarnings("deprecation")
private void doInvoke(final ResourceMethodDescriptor descriptor, final RequestExecutionCallback<Object> callback, final RequestExecutionReportBuilder requestExecutionReportBuilder, final Object resource, final ServerResourceContext resourceContext, final Object... arguments) throws IllegalAccessException {
final Method method = descriptor.getMethod();
try {
switch(descriptor.getInterfaceType()) {
case CALLBACK:
int callbackIndex = descriptor.indexOfParameterType(ParamType.CALLBACK);
final RequestExecutionReport executionReport = getRequestExecutionReport(requestExecutionReportBuilder);
//Delegate the callback call to the request execution callback along with the
//request execution report.
arguments[callbackIndex] = new Callback<Object>() {
@Override
public void onError(Throwable e) {
callback.onError(e instanceof RestLiServiceException ? e : new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, e), executionReport, resourceContext.getRequestAttachmentReader(), resourceContext.getResponseAttachments());
}
@Override
public void onSuccess(Object result) {
callback.onSuccess(result, executionReport, resourceContext.getResponseAttachments());
}
};
method.invoke(resource, arguments);
// App code should use the callback
break;
case SYNC:
Object applicationResult = method.invoke(resource, arguments);
callback.onSuccess(applicationResult, getRequestExecutionReport(requestExecutionReportBuilder), resourceContext.getResponseAttachments());
break;
case PROMISE:
if (!checkEngine(resourceContext, callback, descriptor, requestExecutionReportBuilder)) {
break;
}
int contextIndex = descriptor.indexOfParameterType(ParamType.PARSEQ_CONTEXT_PARAM);
if (contextIndex == -1) {
contextIndex = descriptor.indexOfParameterType(ParamType.PARSEQ_CONTEXT);
}
// run through the engine to get the context
Task<Object> restliTask = new RestLiParSeqTask(arguments, contextIndex, method, resource);
// propagate the result to the callback
restliTask.addListener(new CallbackPromiseAdapter<>(callback, restliTask, requestExecutionReportBuilder, resourceContext.getRequestAttachmentReader(), resourceContext.getResponseAttachments()));
runTask(restliTask, toPlanClass(descriptor));
break;
case TASK:
if (!checkEngine(resourceContext, callback, descriptor, requestExecutionReportBuilder)) {
break;
}
//addListener requires Task<Object> in this case
@SuppressWarnings("unchecked") Task<Object> task = (Task<Object>) method.invoke(resource, arguments);
if (task == null) {
callback.onError(new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Error in application code: null Task"), getRequestExecutionReport(requestExecutionReportBuilder), resourceContext.getRequestAttachmentReader(), resourceContext.getResponseAttachments());
} else {
task.addListener(new CallbackPromiseAdapter<>(callback, task, requestExecutionReportBuilder, resourceContext.getRequestAttachmentReader(), resourceContext.getResponseAttachments()));
runTask(task, toPlanClass(descriptor));
}
break;
default:
throw new AssertionError("Unexpected interface type " + descriptor.getInterfaceType());
}
} catch (InvocationTargetException e) {
// InvocationTargetException wrapped around the root cause.
if (RestLiServiceException.class.isAssignableFrom(e.getCause().getClass())) {
RestLiServiceException restLiServiceException = (RestLiServiceException) e.getCause();
callback.onError(restLiServiceException, getRequestExecutionReport(requestExecutionReportBuilder), resourceContext.getRequestAttachmentReader(), resourceContext.getResponseAttachments());
} else {
callback.onError(new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, _errorResponseBuilder.getInternalErrorMessage(), e.getCause()), getRequestExecutionReport(requestExecutionReportBuilder), resourceContext.getRequestAttachmentReader(), resourceContext.getResponseAttachments());
}
}
}
use of com.linkedin.restli.server.RestLiServiceException in project incubator-gobblin by apache.
the class LimiterServerResourceTest method testLimitedRequests.
@Test
public void testLimitedRequests() {
ThrottlingPolicyFactory factory = new ThrottlingPolicyFactory();
SharedLimiterKey res1key = new SharedLimiterKey("res1");
SharedLimiterKey res2key = new SharedLimiterKey("res2");
Map<String, String> configMap = ImmutableMap.<String, String>builder().put(BrokerConfigurationKeyGenerator.generateKey(factory, res1key, null, ThrottlingPolicyFactory.POLICY_KEY), CountBasedPolicy.FACTORY_ALIAS).put(BrokerConfigurationKeyGenerator.generateKey(factory, res1key, null, CountBasedPolicy.COUNT_KEY), "100").put(BrokerConfigurationKeyGenerator.generateKey(factory, res2key, null, ThrottlingPolicyFactory.POLICY_KEY), CountBasedPolicy.FACTORY_ALIAS).put(BrokerConfigurationKeyGenerator.generateKey(factory, res2key, null, CountBasedPolicy.COUNT_KEY), "50").build();
ThrottlingGuiceServletConfig guiceServletConfig = new ThrottlingGuiceServletConfig();
guiceServletConfig.initialize(ConfigFactory.parseMap(configMap));
Injector injector = guiceServletConfig.getInjector();
LimiterServerResource limiterServer = injector.getInstance(LimiterServerResource.class);
PermitRequest res1request = new PermitRequest();
res1request.setPermits(20);
res1request.setResource(res1key.getResourceLimitedPath());
PermitRequest res2request = new PermitRequest();
res2request.setPermits(20);
res2request.setResource(res2key.getResourceLimitedPath());
PermitRequest res3request = new PermitRequest();
res3request.setPermits(100000);
res3request.setResource("res3");
Assert.assertEquals(limiterServer.getSync(new ComplexResourceKey<>(res1request, new EmptyRecord())).getPermits(), new Long(20));
Assert.assertEquals(limiterServer.getSync(new ComplexResourceKey<>(res1request, new EmptyRecord())).getPermits(), new Long(20));
Assert.assertEquals(limiterServer.getSync(new ComplexResourceKey<>(res1request, new EmptyRecord())).getPermits(), new Long(20));
Assert.assertEquals(limiterServer.getSync(new ComplexResourceKey<>(res1request, new EmptyRecord())).getPermits(), new Long(20));
Assert.assertEquals(limiterServer.getSync(new ComplexResourceKey<>(res1request, new EmptyRecord())).getPermits(), new Long(20));
try {
// out of permits
limiterServer.getSync(new ComplexResourceKey<>(res1request, new EmptyRecord())).getPermits();
Assert.fail();
} catch (RestLiServiceException exc) {
Assert.assertEquals(exc.getStatus(), HttpStatus.S_403_FORBIDDEN);
}
Assert.assertEquals(limiterServer.getSync(new ComplexResourceKey<>(res2request, new EmptyRecord())).getPermits(), new Long(20));
Assert.assertEquals(limiterServer.getSync(new ComplexResourceKey<>(res2request, new EmptyRecord())).getPermits(), new Long(20));
// out of permits
try {
// out of permits
limiterServer.getSync(new ComplexResourceKey<>(res2request, new EmptyRecord())).getPermits();
Assert.fail();
} catch (RestLiServiceException exc) {
Assert.assertEquals(exc.getStatus(), HttpStatus.S_403_FORBIDDEN);
}
// No limit
Assert.assertTrue(limiterServer.getSync(new ComplexResourceKey<>(res3request, new EmptyRecord())).getPermits() >= res3request.getPermits());
}
use of com.linkedin.restli.server.RestLiServiceException in project rest.li by linkedin.
the class LatencyInstrumentationResource method create.
/**
* This is the "upstream endpoint" which is queried directly by the integration test.
* This endpoint makes a call to {@link #batchPartialUpdate(BatchPatchRequest)} (the "downstream endpoint"),
* then packs all the client-side timing data into the original server-side request context.
*/
@ReturnEntity
@RestMethod.Create
public CreateKVResponse<Long, InstrumentationControl> create(InstrumentationControl control) {
final boolean forceException = control.isForceException();
final boolean useScatterGather = control.isUseScatterGather();
final String uriPrefix = control.getServiceUriPrefix();
// Build the downstream request
final BatchPartialUpdateEntityRequestBuilder<Long, InstrumentationControl> builder = new LatencyInstrumentationBuilders().batchPartialUpdateAndGet();
final PatchRequest<InstrumentationControl> patch = PatchGenerator.diffEmpty(control);
for (long i = 0; i < DOWNSTREAM_BATCH_SIZE; i++) {
builder.input(i, patch);
}
final BatchPartialUpdateEntityRequest<Long, InstrumentationControl> request = builder.build();
// Set up the Rest.li client config
final RestLiClientConfig clientConfig = new RestLiClientConfig();
clientConfig.setUseStreaming(control.isUseStreaming());
if (useScatterGather) {
clientConfig.setScatterGatherStrategy(new DefaultScatterGatherStrategy(new DummyUriMapper()));
}
final TransportClient transportClient = new HttpClientFactory.Builder().build().getClient(Collections.emptyMap());
final RestClient restClient = new ForceScatterGatherRestClient(new TransportClientAdapter(transportClient), uriPrefix, clientConfig);
final RequestContext serverRequestContext = getContext().getRawRequestContext();
final RequestContext clientRequestContext = new RequestContext();
// Load the timing importance threshold from the server context into the client context
clientRequestContext.putLocalAttr(TimingContextUtil.TIMING_IMPORTANCE_THRESHOLD_KEY_NAME, serverRequestContext.getLocalAttr(TimingContextUtil.TIMING_IMPORTANCE_THRESHOLD_KEY_NAME));
try {
// Make the request, then assert that the returned errors (if any) are as expected
BatchKVResponse<Long, UpdateEntityStatus<InstrumentationControl>> response = restClient.sendRequest(request, clientRequestContext).getResponseEntity();
final Map<Long, ErrorResponse> errors = response.getErrors();
if (forceException && errors.isEmpty()) {
throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Expected failures for the downstream batch request, but found none.");
}
if (!forceException && !errors.isEmpty()) {
throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Expected no failures for the downstream batch request, but found some.");
}
for (ErrorResponse errorResponse : errors.values()) {
if (!DOWNSTREAM_ERROR_CODE.equals(errorResponse.getCode())) {
throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Encountered a downstream failure with an unexpected or missing error code.");
}
}
} catch (RemoteInvocationException e) {
throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Downstream failures should be batch entry failures, but encountered a top-level request failure.", e);
}
Map<TimingKey, TimingContextUtil.TimingContext> clientTimingsMap = TimingContextUtil.getTimingsMap(clientRequestContext);
Map<TimingKey, TimingContextUtil.TimingContext> serverTimingsMap = TimingContextUtil.getTimingsMap(serverRequestContext);
// Load all client timings into the server timings map
serverTimingsMap.putAll(clientTimingsMap);
getContext().setResponseHeader(HAS_CLIENT_TIMINGS_HEADER, Boolean.TRUE.toString());
if (forceException) {
throw new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST, "You wanted me to fail, so I failed.").setCode(UPSTREAM_ERROR_CODE);
}
return new CreateKVResponse<>(1L, control);
}
use of com.linkedin.restli.server.RestLiServiceException in project rest.li by linkedin.
the class LatencyInstrumentationResource method batchPartialUpdate.
/**
* This is the "downstream endpoint", queried by {@link #create(InstrumentationControl)} (the "upstream endpoint").
*/
@ReturnEntity
@RestMethod.BatchPartialUpdate
public BatchUpdateEntityResult<Long, InstrumentationControl> batchPartialUpdate(BatchPatchRequest<Long, InstrumentationControl> batchPatchRequest) throws DataProcessingException {
final Map<Long, UpdateEntityResponse<InstrumentationControl>> results = new HashMap<>();
final Map<Long, RestLiServiceException> errors = new HashMap<>();
for (Map.Entry<Long, PatchRequest<InstrumentationControl>> entry : batchPatchRequest.getData().entrySet()) {
// Render each patch into a normal record so we know whether or not to force a failure
InstrumentationControl control = new InstrumentationControl();
PatchApplier.applyPatch(control, entry.getValue());
if (control.isForceException()) {
RestLiServiceException error = new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST, "You wanted me to fail, so I failed.").setCode(DOWNSTREAM_ERROR_CODE);
errors.put(entry.getKey(), error);
} else {
results.put(entry.getKey(), new UpdateEntityResponse<>(HttpStatus.S_200_OK, control));
}
}
return new BatchUpdateEntityResult<>(results, errors);
}
use of com.linkedin.restli.server.RestLiServiceException in project rest.li by linkedin.
the class GreetingsResourceImpl method batchGet.
@RestMethod.BatchGet
public Map<Long, Greeting> batchGet(Set<Long> ids) {
Map<Long, Greeting> batch = new HashMap<>();
Map<Long, RestLiServiceException> errors = new HashMap<>();
for (long id : ids) {
Greeting g = _db.get(id);
if (g != null) {
batch.put(id, g);
} else {
errors.put(id, new RestLiServiceException(HttpStatus.S_404_NOT_FOUND));
}
}
return new BatchResult<>(batch, errors);
}
Aggregations