1

I have REST endpoint which has injected services.

@Singleton
@Path("/v1/service")
public class MyService {

    @Inject
    private TokenService tokenService;

    @Inject
    private InfoService infoService;

    @GET
    @Path("/info")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public InfoResponse getInfo(@HeaderParam("Authorization") String token){

        tokenService.validateToken(token);

        List<String> info = infoService.getInfo();

        // processing info code, throwing WebServiceException if something wrong

       return new InfoResponse(info);
    }
}

Some of them validates data, for example token, and throws RestServiceException exception if it is incorrect. Exceptions are processed by ExceptionMapper so appropriate Response is returned. Other services return/process information.

My custom exception class with additional fields:

public class RestServiceException extends WebServiceException {

    public Integer httpStatus;

    public String message;
}

Example service method:

public User getUser(Long userId){

    User user = userMapper.getUser(userId);

    if (user == null){
        String msg = "Invalid user: " + userId;
        logger.debug(msg);
        throw new RestServiceException(HttpStatus.SC_NOT_FOUND, InternalStatus.INVALID_USER, msg);
    }

    return user;
}

Is good practice to throw RestServiceException in injected services? How to design code to facilitate testing? Where to put validation methods - service or static class?

Justinas Jakavonis
  • 8,220
  • 10
  • 69
  • 114

1 Answers1

1

Is good practice to throw WebServiceException in injected services?

I wouldn't.

  1. Make services not reusable outside jax-rs applications (might not be much problem for you).
  2. Breaks the "tiered" architecture rules; lower levels shouldn't know anything about upper levels. You should just throw a normal service level exception, catch the exception in the resource as then from there if you want to wrap in a WebApplicationException, then do so.

    Maybe just throwing a WebApplicationException isn't considered "knowing about the upper layer", but personally I think it does, as the exception type is specific to that upper layer.

How to design code to facilitate testing?

Use constructor injection instead of field injection. And if you need to, it's easier to provide mock services to the resource.

public class MyService {

    private final TokenService tokenService;
    private final InfoService infoService;

    @Inject
    public MyService(TokenService tokenService,
                     InfoService infoService) {
        this.tokenService = tokenService;
        this.infoService = infoService;
    }
}

Where to put validation methods - service or static class?

This doesn't really make sense. If by "static class" you mean singleton pattern singleton, then no definitely not that. Using Inversion of control the way you're currently doing is your better bet.


UPDATE

I think I read you question wrong. For Some reason I read your WebServiceException as the JAX-RS WebApplicationException.

I guess the rules I mentioned above don't apply. But I would probably change the name of the exception to something other than WebServiceException. That ties it to much to the upper "web" layer. Name the exception something specific to that service.

In regard to handing the exception on the resource level, if you don't want to, you don't need to do anything with it, if an ExceptionMapper is handling it. Or you can catch it if you want and wrap it in a WebApplicationException.

You can check out the bottom of this post, where it lists all the sub classes of WebApplicationException. If you want, you can just wrap the exception in one of those and throw it. Those exceptions are all mappped to status codes.

Community
  • 1
  • 1
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • I have RestServiceException extends WebServiceException with additional fields HTTP status and message. It is thrown in injected services. I am considering that service should throw checked exception without HTTP status which should be handled and processed to RestServiceException with status in the main REST endpoint service. – Justinas Jakavonis Jul 27 '16 at 12:35
  • Unchecked exception looks more suitable for validation, for example not found user. – Justinas Jakavonis Jul 27 '16 at 12:59
  • Why do you need to throw an exception at all. Exceptions should be thrown for non-recoverable cases. For auth, a user not found is not a non-recoverable case. The auth is working fine, as it found out the user is not verfied. Maybe just return a boolean. – Paul Samsotha Jul 27 '16 at 13:12
  • Updated the thread with example method. Service method loads an object from DB and validates it. I have made this because it used in various endpoint methods, I can do all necessary operations in 1 method so exception is thrown instead of returning null. – Justinas Jakavonis Jul 27 '16 at 13:28