I have an interface:
public interface ThirdPartySystemCaller {
void sendRequest(String request) throws ThirdPartySystemException;
}
And implementation:
#Slf4j
#Service
public class ThirdPartySystemCallerImpl implements ThirdPartySystemCaller {
#Override
public void sendRequest(String request) throws ThirdPartySystemException {
if (request == null) throw new ThirdPartySystemException();
log.info("send: {}", request);
}
}
And I have a CryptoService witch can sign request:
public interface CryptoService {
String signRequest(String request) throws CryptoException;
}
And It implementation:
#Slf4j
#Service
public class CryptoServiceImpl implements CryptoService {
#Override
public String signRequest(String request) throws CryptoException {
if (request.length() > 100) throw new CryptoException(); //just for example
return "signed " + request;
}
}
Now, I can use these services:
String signedRequest = cryptoService.signRequest("Hello");
thirdPartySystemCaller.sendRequest(signedRequest);
But I need to call both services each time. I want to create Proxy:
#Slf4j
#Service
public class ThirdPartySystemCallerSignedProxy implements ThirdPartySystemCaller {
private final ThirdPartySystemCaller thirdPartySystemCaller;
private final CryptoService cryptoService;
public ThirdPartySystemCallerSignedProxy(ThirdPartySystemCaller thirdPartySystemCaller, CryptoService cryptoService) {
this.thirdPartySystemCaller = thirdPartySystemCaller;
this.cryptoService = cryptoService;
}
#Override
public void sendRequest(String request) throws ThirdPartySystemException {
String signedRequest = cryptoService.signRequest(request);
thirdPartySystemCaller.sendRequest(signedRequest);
}
}
But my ThirdPartySystemCallerSignedProxy implement ThirdPartySystemCaller interface and sendRequest method throw only ThirdPartySystemException. But if cryptoService throw CryptoException I need throw it too.
How can I do it?
I was thinking to make unchecked exceptions, But I need to be checked.
Create base exception
You can create abstract exception BusinessException which can be a base exception for ThirdPartySystemException and CryptoException. Now, you can define that sendRequest method throws BusinessException and real exception depends from given problem.
Facade
ThirdPartySystemCallerSignedProxy is a bad name because it reminds Proxy pattern which is not what you have implemented. This class reminds Facade pattern because you want to create unified interface with simpler API for two different interfaces. In that case you can wrap CryptoException if it will be thrown into ThirdPartySystemException or also create base exception and declare it in method. It is even better because you do not know which kind of exception will be thrown but for sure it will be BusinessException.
Chain of Responsibility
Many libraries use Chain of Responsibility to handle request -> response communication. All chain cells need to implement the same interface with base exception in declaration if needed. You can build the chain in bean definition. It is a little bit easier to maintain because all cells are independent and does not have to know about each other as in Facade. You can build chain in #Bean method declaration like below:
#Bean
public ServiceChainCell thirdPartyCaller() {
CryptoService crypto = cryptoService();
ThirdPartySystemCaller caller = thirdPartySystemCaller();
// Create chain
crypto.setNext(caller);
return crypto;
}
setNext method comes from ServiceChainCell interface which also should have sendRequest(String request) method.
Read more about these patterns and you will find the best solution for you.
Related
In Spring, I'd like to add an exception handler programmatically, without relying on the system to scan for methods annotated with #ExceptionHandler. Is that possible?
Currently, I'm relying on the system to scan for the following method:
#ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public ResponseEntity<String> handle(
final HttpRequestMethodNotSupportedException httpRequestMethodNotSupportedException,
final HttpServletRequest httpServletRequest,
final HttpServletResponse httpServletResponse)
{
return ResponseEntity
.status(METHOD_NOT_ALLOWED)
.body(format(
"Unsupported method '%s' for URI '%s'; expected method among: %s.",
httpRequestMethodNotSupportedException.getMethod(),
httpServletRequest.getRequestURI(),
join(", ", asList(httpRequestMethodNotSupportedException.getSupportedMethods())
.stream()
.map(object -> "'" + object + "'")
.collect(toList()))));
}
And it works as expected, handling the HttpRequestMethodNotSupportedException and serializing the response as expected:
Unsupported method 'DELETE' for URI '/example'; expected method among: 'GET', 'POST'.
However, I know of no way to, say, use the Java config to indicate that it should use a particular class, or a particular instance, to handle specific exceptions.
I had a similar issue with adding implementations of ResponseBodyAdvice programmatically, and there is a way to do that - see here:
#Configuration
#ComponentScan(basePackageClasses = ExceptionHandler.class)
public class ConfigurationExample
extends WebMvcConfigurationSupport
{
#Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter(
#Qualifier(value = "mvcContentNegotiationManager") final ContentNegotiationManager contentNegotiationManager,
#Qualifier(value = "mvcConversionService") final FormattingConversionService conversionService,
#Qualifier(value = "mvcValidator") final Validator validator)
{
final RequestMappingHandlerAdapter requestMappingHandlerAdapter = super.requestMappingHandlerAdapter(contentNegotiationManager, conversionService, validator);
requestMappingHandlerAdapter.setResponseBodyAdvice(Arrays.asList(
new ResponseBodyAdviceExample()));
return requestMappingHandlerAdapter;
}
}
Is there a similar method for adding custom exception handlers - or any one?
For background, my goal is to create a library of exception handlers which I can use across projects.
I don't know if there is an idiomatic way to do it, but I found a way to add exception handlers programmatically.
(I'll wait a few weeks to mark this as accepted, if anyone wants to offer an alternative.)
Code here:
https://gist.github.com/drewctaylor/f838eb8304d7c526872ed29934a1e830
Ultimately, I subclassed ExceptionHandlerExceptionResolver. Under the hood, ExceptionHandlerExceptionResolver essentially maps from java.lang.Class<java.lang.Exception> to java.lang.reflect.Method; if an exception of the given type occurs, the system returns the given method.
This implementation accepts a list of mappings from java.lang.Class<java.lang.Exception> to java.lang.reflect.Method. If an exception of a type in that list occurs, it returns the associated method; otherwise, defers to the superclass.
Code for the implementation, ExceptionHandlerExceptionResolverFromList:
public class ExceptionHandlerExceptionResolverFromList
extends ExceptionHandlerExceptionResolver
{
private final Map<Class<?>, ExceptionHandlerWithExceptionClassAndMethod<?>> map;
public ExceptionHandlerExceptionResolverFromList(
final List<ExceptionHandlerWithExceptionClassAndMethod<?>> list)
{
requireNonNull(list);
map = list.stream().collect(toMap(ExceptionHandlerWithExceptionClassAndMethod::getExceptionClass, Function.identity()));
}
#Nullable
protected ServletInvocableHandlerMethod getExceptionHandlerMethod(
#Nullable final HandlerMethod handlerMethod,
final Exception exception)
{
requireNonNull(exception);
return map.containsKey(exception.getClass()) ?
new ServletInvocableHandlerMethod(map.get(exception.getClass()), map.get(exception.getClass()).getMethod()) :
super.getExceptionHandlerMethod(handlerMethod, exception);
}
}
The mapping is defined by an implementation of the interface ExceptionHandlerWithExceptionClassAndMethod:
public interface ExceptionHandlerWithExceptionClassAndMethod<E extends Exception>
{
Class<E> getExceptionClass();
Method getMethod();
}
A specific implementation is ExceptionHandlerForHttpRequestMethodNotSupportedException, similar to the example in the question:
public class ExceptionHandlerForHttpRequestMethodNotSupportedException
implements ExceptionHandlerWithExceptionClassAndMethod<HttpRequestMethodNotSupportedException>
{
#Override
public Class<HttpRequestMethodNotSupportedException> getExceptionClass()
{
return HttpRequestMethodNotSupportedException.class;
}
#Override
public Method getMethod()
{
try
{
return getClass().getDeclaredMethod(
"handle",
HttpRequestMethodNotSupportedException.class,
HttpServletRequest.class,
HttpServletResponse.class);
}
catch (Exception exception)
{
throw new RuntimeException(exception);
}
}
public ResponseEntity<String> handle(
final HttpRequestMethodNotSupportedException httpRequestMethodNotSupportedException,
final HttpServletRequest httpServletRequest,
final HttpServletResponse httpServletResponse)
{
return ResponseEntity.status(METHOD_NOT_ALLOWED).body(
format(
"Unsupported method '%s' for URI '%s'; expected method among: %s.",
httpRequestMethodNotSupportedException.getMethod(),
httpServletRequest.getRequestURI(),
join(", ", asList(httpRequestMethodNotSupportedException.getSupportedMethods()).stream().map(object -> "'" + object + "'").collect(toList()))));
}
}
Note that the above combines the mapping with the implementation of the handler, which is not strictly necessary, but presently seems appropriate.
To add the handler to the application, extend the Configuration from WebMvcConfigurationSupport and override createExceptionHandlerExceptionResolver to return the instance of ExceptionHandlerExceptionResolverFromList:
#org.springframework.context.annotation.Configuration
public class Configuration
extends WebMvcConfigurationSupport
{
protected ExceptionHandlerExceptionResolver createExceptionHandlerExceptionResolver()
{
return new ExceptionHandlerExceptionResolverFromList(asList(
new ExceptionHandlerForHttpRequestMethodNotSupportedException()));
}
}
The application will now use ExceptionHandlerForHttpRequestMethodNotSupportedException to handle HttpRequestMethodNotSupportedException; for other exceptions, it will use any other handlers defined.
java 8, spring, rest
I am trying to capture the Response that comes from exception mapper, and do something with it in the caller which throws the exception. Thanks.
#Provider
public class CustomerExceptionHandler implements ExceptionMapper<CustomerException>
{
#Override
public Response toResponse(CustomerException exception)
{
return Response.status(Status.BAD_REQUEST).entity(CustomerException.getMessage()).build();
}
}
public class CustomerException extends Exception implements Serializable
{
private static final long serialVersionUID = 1L;
public CustomerException() {
super();
}
public CustomerException(String msg) {
super(msg);
}
public CustomerException(String msg, Exception e) {
super(msg, e);
}
}
public class ExceptionDemo{
public void getExceptionResponse(){
//do something
throw new CustomerException("Something is wrong");// CustomerExceptionHandler is going to return me a Response, how can I capture the response here?
//capture response and do something with it
}
}
I'm not sure ExceptionMappers work in the way you think they do.
When some code in the endpoint throws an exception, and this exception percolates all the way out of the endpoint and back into the container itself (Spring in this case), then the registered ExceptionMappers are consulted to see if they match the thrown exception, and the relevant one's public Response toResponse(T e) {} method is called to transform it into a Response.
The ExceptionMapper doen't get called as part of your endpoint code, and you won't be able to take action based on its resultant Response because it hasn't yet been called. You just need to throw the exception out of the endpoint.
I'm trying to enrich the SLF4J MDC on each request with the user's ID. The problem is that the ID can be passed in many ways, sometimes as a path parameter, sometimes in the body, and sometimes injected by a custom ValueFactoryProvider that first decrypts it.
If I could somehow access all the injected (i.e. already deserialized) parameter values, I could handle all these cases easily.
E.g.
For a resource such as:
#GET
//#Encrypted params are injected by a custom ValueFactoryProvider
public Something getSomething(#Encrypted("userId") String userId) {
return ...;
}
#POST
public Something getSomething(#RequestBody RequestWithUserId requestWithUserId) {
return ...;
}
I could have a filter such as:
public class MdcFilter implements ContainerRequestFilter, ContainerResponseFilter {
#Context
private ResourceInfo resourceInfo;
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
Method theMethod = resourceInfo.getResourceMethod();
for (Parameter parameter : theMethod.getParameters()) {
//Deal with the #Encrypted case
if (parameter.isAnnotationPresent(Encrypted.class) && parameter.getAnnotation(Encrypted.class).value().equals("userId")) {
MDC.put("userId", somehowGetTheValue());
}
//Deal with the #RequestBody case
if (parameter.isAnnotationPresent(RequestBody.class) && parameter.getType().equals(RequestWithUserId.class)) {
MDC.put("userId", ((RequestWithUserId)somehowGetTheValue()).getUserId());
}
... //other possibilities
}
}
#Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
MDC.clear();
}
}
But I don't see a way to implement somehowGetTheValue either from a ContainerRequestFilter an interceptor or anything else...
Jersey uses HK2 under the hood for dependency injection. And HK2 has AOP support. One option for your use case would be use this AOP support. All you need to do is implement a MethodInterceptor and an InterceptionService. In the MethodInterceptor, you can get all the arguments from the MethodInvocation and you can get parameter annotation from the Method
class MyMethodInteceptor implements MethodInterceptor {
#Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Method method = invocation.getMethod();
Object[] args = invocation.getArguments();
// do your logging or whatever with the args.
// invoke method and get return value.
Object returnValue = invocation.proceed();
// if you want to do something with the return
// value before returning it, you can.
return returnValue;
}
}
To use the interceptor, you configure the InterceptionService.
public class MyInterceptionService implements InterceptionService {
private final static MethodInterceptor METHOD_INTERCEPTOR
= new MyMethodInterceptor();
private final static List<MethodInterceptor> METHOD_LIST
= Collections.singletonList(METHOD_INTERCEPTOR);
#Override
public Filter getDescriptorFilter() {
return BuilderHelper.allFilter();
}
#Override
public List<MethodInterceptor> getMethodInterceptors(Method method) {
// you implement shouldIntercept
if (shouldIntercept(method)) {
return METHOD_LIST;
}
return null;
}
#Override
public List<ConstructorInterceptor> getConstructorInterceptors(Constructor<?> constructor) {
return null;
}
}
You determine which method should be intercepted in the getMethodInterceptors() method. If the method should be intercepted, then return a list of interceptors, otherwise return null. A common way of handling this is to create a custom annotation and just annotate the method. The in the above method, just check
if (method.isAnnotationPresent(YourAnno.class)) {
return METHOD_LIST;
}
To make it all work, you just need to register the InteceptionService with HK2. You can do that in an AbstractBinder, which is what is used in a Jersey app to configure your DI.
ResourceConfig config = new ResourceConfig();
config.register(new AbstractBinder() {
#Override
protected void configure() {
bind(MyInterceptionService.class)
.to(InterceptionService.class)
.in(Singleton.class);
}
});
You can see a complete example in this GitHub repo. There is also an official example in the HK2 site. Just see "AOP support" the link at the top of the post.
You can get it like this
StringWriter stringWriter = new StringWriter();
IOUtils.copy(new InputStreamReader(requestContext.getEntityStream()), stringWriter);
System.out.println(stringWriter.toString());// String representation of the payload
requestContext.setEntityInputStream(new ByteArrayInputStream(requestEntity));
Basically the idea is to copy the stream and do any processing and then set the stream back. Because if you don't do that, then in your controller method you would get null, becuase the stream was already read.
I'm using Dropwizard 0.9.2 and I want to create a resource that requires no authentication for GET and requires basic authentication for POST.
I have tried
#Path("/protectedPing")
#Produces(MediaType.TEXT_PLAIN)
public class ProtectedPing {
#GET
public String everybody() {
return "pingpong";
}
#PermitAll
#POST
public String authenticated(){
return "secret pingpong";
}
with
CachingAuthenticator<BasicCredentials, User> ca = new CachingAuthenticator<>(environment.metrics(), ldapAuthenticator, cbSpec);
AdminAuthorizer authorizer = new AdminAuthorizer();
BasicCredentialAuthFilter<User> bcaf = new BasicCredentialAuthFilter.Builder<User>().setAuthenticator(ca).setRealm("test-oauth").setAuthorizer(authorizer).buildAuthFilter();
environment.jersey().register(bcaf);
environment.jersey().register(RolesAllowedDynamicFeature.class);
environment.jersey().register(new AuthValueFactoryProvider.Binder<>(User.class));
environment.jersey().register(new ProtectedPing());
This seems to result in all requests to "/protectedPing" requiring basic auth.
In Dropwizard 0.9.2 the documentation says to create a custom filter if I have a resource that is optionally protected. I'm assuming I need to do that, but I don't know where to start, or if that I what I actually need to do.
this is more of a jersey problem than a dropwizard problem. You can have a look here: https://jersey.java.net/documentation/latest/filters-and-interceptors.html
Essentially what you want is:
Create an annotation that indicates that you want to test for authentication (e.g. #AuthenticatePost)
Create the resource and annotate the correct method with #AuthenticatePost
Create your authentication filter (probably kind of like what you did above).
In the dynamic feature, test for the annotation to be present on the passed in resource. This will hold true for post, false for get. Then register the AuthenticationFilter directly on the resource method instead of globally on the resource.
This would be a semi-complete example of how I would solve this:
public class MyDynamicFeature implements DynamicFeature {
#Override
public void configure(ResourceInfo resourceInfo, FeatureContext context) {
if(resourceInfo.getResourceMethod().getAnnotation(AuthenticateMe.class) != null ) {
context.register(MyAuthFilter.class);
}
}
public class MyAuthFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
// do authentication here
}
}
public #interface AuthenticateMe {
}
#Path("myPath")
public class MyResource {
#GET
public String get() {
return "get-method";
}
#POST
#AuthenticateMe
public String post() {
return "post-method";
}
}
}
Note, the DynamicFeature checks that the Authenticate Annotation is present, before registering the authentication with the feature context.
I hope that helps,
let me know if you have any questions.
I have this question about best practices in following examples:
interface Request;
interface Service {
void process(Request request)
}
class MyService implements Service;
class YourService implements Service;
class MyRequest implements Request;
class YourRequest implements Request;
But how to ensure that MyService will always receive MyRequest and YourService will get YourRequest only, and not in the opposite way? Obvious answer "if-instance-of-check" in MyService.process(...) seems ugly and somehow against SOLID principles. Maybe there are better ways around?
Maybe generics would be good solution? (But then, how to use them in code that has to run under Java 1.4?)
Put simply, you are establishing an interface that you then don't want to adhere to, so it's not really an ideal design.
What I mean is, if MyService implements Service, then it must be able to take any kind of request. Otherwise it isn't following the defined contract.
I would question why you have the Service interface at all in this instance, and if you do need it (for other methods) whether it's appropriate for the process(Request request) method to be on there if subclasses are not going to honour it.
If the design of the contract is that each Service can process any kind of Request, then your implementation of MyService , which only takes MyRequest (and breaks if other kinds of Requests are passed in), is wrong.
If the design of the contract is that Service and Request subclasses maps to each other, e.g., MyService can (and should) only process a MyRequest, then you will need to change the interface of Service. Otherwise, the current interface as written in the question does not do what the question describes it to do. One way to fix is to parameterize the Service interface:
interface Service<R> {
void process(R request);
}
then your concrete MyService will be
public class MyService implements Service<MyRequest> {
public void process (MyRequest r) {/*blah*/}
}
You can see an example of this in action in the JDK - the Comparator interface does exactly this, for exactly the same reason. http://java.sun.com/javase/6/docs/api/java/util/Comparator.html
I cant see why you would, but if you still want to restrict the hierachy of MyRequest to be a request, then you can swap Service<R> with Service<R extends Request>
edit: this obviously doesnt run in 1.4, so to do the same thing[1] , you will need to use a visitor pattern. Its uglier, but 1.4 is ugly =)
interface Service {
void process(Request visitor);
}
interface RequestVisitor {
void visitMyRequest(MyService service);
void visitYourRequest(YourService service);
void visitTheOtherRequest(TheOtherService service);
}
interface Request extends RequestVisitor { /* and any extra methods required for request*/ }
public class MyService implements Service {
public process(Request r) {r.visitMyRequest(this);}
public void doSpecialMyProcessing(MyRequest request) { /* your code using MyRequest*/ }
}
public class YourService implements Service {
public process(Request r) {r.visitYourRequest(this);}
public void doSpecialYourProcessing(YourRequest request) { /* your code using YourRequest */ }
}
public class MyRequest implements Request {
void visitMyRequest(MyService service) {
service.doSpecialMyProcessing(this);
}
void visitYourRequest(YourService service) {
throw new UnsupportedOperation("Cannot call visitYourRequest in MyRequest!");
}
void visitTheOtherRequest(TheOtherService service) {
throw new UnsupportedOperation("Cannot call visitTheOtherRequest in MyRequest!");
}
}
public class YourRequest implements Request {
void visitMyRequest(MyService service) {
throw new UnsupportedOperation("Cannot call visitMyRequest in YourRequest !");
}
void visitYourRequest(YourService service) {
service. doSpecialYourProcessing(this);
}
void visitTheOtherRequest(TheOtherService service) {
throw new UnsupportedOperation("Cannot call visitTheOtherRequest in YourRequest !");
}
}
[1] actually its not the same, because now you will need to write a method for each request subtype. In 1.4, you would have to cast and do instanceof etc, to achieve what 1.5 can do with generics.
In my opinion generics would suit better here. Your interfaces pretend that a service can handle any type of Request. But in fact the implementations of each seem to be tightly coupled.
Anything implementing Service should expect to implements its methods as they are. If MyService and YourService require different method prototypes, then they are different interfaces.
Think of it from the other direction. Without knowing the implementation behind a Service interface, any caller should able to call Service.process(request) with any implementation of Request, and expect to receive a valid response.
try introducing another level of indirection:
interface Module {
Service createService();
Request createRequest();
}
class MyModule implements Module {
Service createService() { return new MyService(); }
Request createRequest() { return new MyRequest(); }
}
class YourModule implements Module {
Service createService() { return new YourService(); }
Request createRequest() { return new YourRequest(); }
}