I am using smtp api which throws MessageException and IOException
But in our application, we need to have wrapper exception for both.
Is it possible to write wrapper exception for this? like custom exception?
Sure. Exceptions just are, and can wrap anything; you don't need to write them as specifically wrapping only IOException or MessageExceptions.
public class MyCustomException extends Exception {
public MyCustomException(String msg) {
super(msg);
}
public MyCustomException(String msg, Throwable cause) {
super(msg, cause);
}
}
The above is what all custom exceptions look like (where relevant they might have a few more fields that register specific info for a specific failure, e.g. SQLException has methods to ask for the DB 'error code'), but they all at least have the above.
Then, to wrap:
public void myMethod() throws MyException {
try {
stuffThatThrowsIOEx();
stuffThatThrowsMessageEx();
} catch (MessageException | IOException e) {
throw new MyException("Cannot send foo", e);
}
}
NB: The string you pass to your MyException should be short, should not use either caps or exclamation points, or for that matter any other punctuation at the end of it. In addition, include actual relevant content there too: For example, the user you tried to send a message for (the point is, whatever you include there as a string constant needs to be simple, short, and not end in punctuation).
Consider to create a root Exception container as
public class GeneralExceptionContainer extends RuntimeException{
private Integer exceptionCode;
private String message;
public GeneralExceptionContainer(String argMessage, Integer exceptionCode) {
super(argMessage);
this.exceptionCode = exceptionCode;
this.message = argMessage;
}
public GeneralExceptionContainer(Throwable cause, Integer exceptionCode, String argMessage) {
super(argMessage, cause);
this.exceptionCode = exceptionCode;
this.message = argMessage;
}
}
With some enumeration or serialization requirement you can add exceptionCode as well
public enum ExceptionCode {
SECTION_LOCKED(-0),
MAPPING_EXCEPTION(-110)
private final int value;
public int getValue() {
return this.value;
}
ExceptionCode(int value) {
this.value = value;
}
public static ExceptionCode findByName(String name) {
for (ExceptionCode v : values()) {
if (v.name().equals(name)) {
return v;
}
}
return null;
}
}
Then extend your customException from root GeneralException Containner
public class CustomException extends GeneralExceptionContainer {
public MappingException(ExceptionCode exceptionCode) {
super(exceptionCode.name(), exceptionCode.getValue());
}
}
Related
I have below piece of code in my spring boot app, which validates email addresses
class EmailValidation {
public static void validate(List<String> s){
try {
for (String address : s) {
if (s == null || s.indexOf("#") < 0) {
throw new InvalidEmailAddressException("Email address is invalid ");
}
new InternetAddress(s);
}
} catch(AddressException e){
LOGGER.Error("Please validate email addresses");
}
catch(InvalidEmailAddressesException e){
LOGGER.error(e.getMessage());
}
}
class InvalidEmailAddressException extends Exception {
public InvalidEmailAddressException(String message) {
super(message)
}
}
}
I want to write a Junit test which will verify that that InvalidEmailAddressesException was thrown and CAUGHT. How can I do that in JUnit?
In general I agree with the comments that such a test is probably unnecessary.
However, if I wanted to test something like that I would test the two cases separately and that requires a small modification to your code.
Firstly I would construct a method that only throws the exception if there is one.
public static void checkAddresses(List<String> s) throws AddressException, InvalidEmailAddressException {
for (String address : s) {
if (s == null || s.indexOf("#") < 0) {
throw new InvalidEmailAddressException("Email address is invalid ");
}
new InternetAddress(s);
}
}
then I would use it in your code like that:
class EmailValidation {
public static void validate(List<String> s){
try {
checkAddresses(s); // a wrapper method that throws the expected exceptions
} catch(AddressException e){
LOGGER.Error("Please validate email addresses");
}
catch(InvalidEmailAddressesException e){
LOGGER.error(e.getMessage());
}
}
// add checkAddresses here or somewhere appropriately
class InvalidEmailAddressException extends Exception {
public InvalidEmailAddressException(String message) {
super(message)
}
}
}
Then, I would write separate tests for checkAddresses that tests both if an exception is expected or not and separate tests for validate, (possibly with the same input that was given to checkAddresses) that should pass if an exception isn't thrown.
Also, if you would like to verify your logs may be you could try something like that.
Indeed using java Exception for common cause is considered a bad practice, and as #Michael said, Exceptions must be exceptional, because
they break flow control
they are slow (more details here How slow are Java exceptions?)
they do not mix with functional paradigm (where Java is in part going to with the addition of lamda-expressions
However, creating a custom object for wrapping validation data is a good thing and InvalidEmailAddressException can be turned into CheckedEmail:
import java.util.List;
import java.util.stream.Collectors;
public class EmailValidator {
public List<CheckedEmail> validate(List<String> emailAddresses) {
return emailAddresses.stream().map(this::validate).collect(Collectors.toList());
}
public CheckedEmail validate(String emailAddress) {
String[] emailParts = emailAddress.toString().split( "#", 3 );
final boolean valid;
if ( emailParts.length != 2 ) {
valid = false;
} else {
// More validation can go here using one or more regex
valid = true;
}
return new CheckedEmail(emailAddress, valid);
}
public static final class CheckedEmail {
private final String emailAddress;
private final boolean valid;
private CheckedEmail(String emailAddress, boolean valid) {
this.emailAddress = emailAddress;
this.valid = valid;
}
public String getEmailAddress() {
return emailAddress;
}
public boolean isValid() {
return valid;
}
}
}
This in turn can be tested quite easily (and improved with a parameterized test):
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
public class EmailValidatorTest {
private final EmailValidator emailValidator = new EmailValidator();
#Test
public void invalid_email() {
EmailValidator.CheckedEmail checkedEmail = emailValidator.validate("missing.an.at.symbol");
assertThat(checkedEmail.isValid()).isFalse();
}
#Test
public void valid_email() {
EmailValidator.CheckedEmail checkedEmail = emailValidator.validate("at.symbol#present");
assertThat(checkedEmail.isValid()).isTrue();
}
#Test
public void multiple_email_addresses() {
List<String> emailAddresses = Arrays.asList("missing.an.at.symbol", "at.symbol#present");
List<EmailValidator.CheckedEmail> checkedEmails = emailValidator.validate(emailAddresses);
assertThat(checkedEmails)
.extracting(ce -> ce.getEmailAddress() + " " + ce.isValid())
.containsExactly(
"missing.an.at.symbol false",
"at.symbol#present true");
}
}
If somewhere the point is just to log this, then:
List<EmailValidator.CheckedEmail> checkedEmails = emailValidator.validate(emailAddresses);
checkedEmails.stream()
.filter(ce -> !ce.isValid())
.map(ce -> String.format("Email address [%s] is invalid", ce.getEmailAddress()))
.forEach(logger::error);
Hope this helps !
Don't approach testing that way. You should test only the specified behaviour of your code, not its implementation details.
If the method you are testing delegates to a method that throws a checked exception, and the method you are testing does not also declare that it throws that checked exception, the compiler will enforce that the method catches the exception. So in that case a unit test is unnecessary.
If the method you are testing delegates to a method that throws an unchecked exception, consult the specification of the method to determine whether it is acceptable for the method under test to also throw (propagate) that exception. If it is not acceptable for it to propagate the exception, then you should create a test case that causes the the method delegated to to throw that unchecked exception. If the method propagates the exception, the test case will fail. How to do that? That depends on the method being delegated to, but in most cases you will need to use Dependency Injection to supply a mock object that throws the exception.
I am trying to generate a very simple code with Byte Buddy.
I have a POJO class where some fields are annotated with #SecureAttribute, For such fields I would like to override getter implementation and redirect the call to a SecurityService.getSecureValue() implementation.
Original class:
public class Properties {
#SecureAttribute
protected String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
Desired Proxy:
public class PropertiesProxy {
private SecurityService securityService;
public void setSecurityService(SecurityService var1) {
this.securityService = var1;
}
public SecurityService getSecurityService() {
return this.securityService;
}
#Override
public String getPassword() {
return securityService.getSecureValue(password);
}
}
Emitting a field was easy but overriding a method becomes complicated. I have found a number of samples relative to my task which I try to apply but do not seem to get the required result.
So my major question is: how do I trace and debug the code generator? First thing I've learned was to print the class to file:
DynamicType.Unloaded<?> unloadedType = byteBuddy.make();
unloadedType.saveIn(new File("d:/temp/bytebuddy"));
This gives me an output where the extra field was added but not a glance of the getter override (disassembled from .class file):
public class PropertiesImpl$ByteBuddy$OLlyZYNY extends PropertiesImpl {
private SecurityService securityService;
public void setSecurityService(SecurityService var1) {
this.securityService = var1;
}
public SecurityService getSecurityService() {
return this.securityService;
}
public PropertiesImpl$ByteBuddy$OLlyZYNY() {
}
}
Here I do not exactly understand how to look for the error. Does it mean that I used totally wrong method implementation and Byte Buddy simply skipped it? Or am I wrong with ElementMatchers? Is there some trace or whatever that will give me a clue how to fix my code?
Current implementation:
private Class<?> wrapProperties() throws IOException {
DynamicType.Builder<?> byteBuddy = new ByteBuddy()
.subclass(PropertiesImpl.class)
.defineProperty("securityService", SecurityService.class);
Arrays.stream(PropertiesImpl.class.getDeclaredFields())
.filter(item -> item.getAnnotation(SecureAttribute.class) != null)
.forEach(item -> byteBuddy
.method(ElementMatchers.named(getGetterBeanName(item)))
.intercept(new GetterWrapperImplementation(item)));
DynamicType.Unloaded<?> unloadedType = byteBuddy.make();
unloadedType.saveIn(new File("d:/temp/bytebuddy"));
Class<?> wrapperClass = unloadedType.load(PropertiesImpl.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
return wrapperClass;
}
public static class GetterWrapperImplementation implements Implementation {
public static final TypeDescription SS_TYPE;
public static final MethodDescription SS_GET_SECURE_VALUE;
private final Field filed;
static {
try {
SS_TYPE = new TypeDescription.ForLoadedType(SecurityService.class);
SS_GET_SECURE_VALUE = new MethodDescription.ForLoadedMethod(SecurityService.class.getDeclaredMethod("getSecureValue", String.class));
}
catch (final NoSuchMethodException | SecurityException e) {
throw new RuntimeException(e);
}
}
public GetterWrapperImplementation(Field filed) {
this.filed = filed;
}
#Override
public InstrumentedType prepare(final InstrumentedType instrumentedType) {
return instrumentedType;
}
#Override
public ByteCodeAppender appender(final Target implementationTarget) {
final TypeDescription thisType = implementationTarget.getInstrumentedType();
return new ByteCodeAppender.Simple(Arrays.asList(
TypeCreation.of(SS_TYPE),
// get securityService field
MethodVariableAccess.loadThis(),
FieldAccess.forField(thisType.getDeclaredFields()
.filter(ElementMatchers.named("securityService"))
.getOnly()
).read(),
// get secure field
MethodVariableAccess.loadThis(),
FieldAccess.forField(thisType.getDeclaredFields()
.filter(ElementMatchers.named(filed.getName()))
.getOnly()
).read(),
MethodInvocation.invoke(SS_GET_SECURE_VALUE),
MethodReturn.of(TypeDescription.STRING)
));
}
}
What I know for the fact is that breakpoints inside ByteCodeAppender appender(final Target implementationTarget) do not get hit, but again not sure how to interpret this.
Thanks.
The Byte Buddy DSL is immutable. This means that you always have to call:
builder = builder.method(...).intercept(...);
Your forEach does not do what you expect for this reason.
As for your implementation, you can just use MethodCall on a field and define the other field as an argument.
I'm writing a messaging system to queue actions for my program to execute. I need to be able to pass various objects by the messages. I currently have a Msg object that accepts (Action enum, Data<?>...object). The Data object is intended to be a wrapper for any object I might pass.
Currently the Data object uses this code, with generics:
public class Data<T> {
private T data;
public Data(T data){
this.data = data;
}
public T getData(){
return data;
}
}
The Msg object takes Data<?>... type, so Msg has a Data<?>[] field.
If getData() is called on a Data<?> object, it returns the Object type. Obviously not ideal.
I need to be able to pass, say, Image objects as well as String objects. I'm certain there's a better way of passing arbitrary data.
The reason you're having trouble is that you're trying to get the static typing system of Java to do something that it can't. Once you convert from a Data<T> to a Data<?>, whatever T was is effectively lost. There's no clean way to get it back.
The quickest way to get it to work (from what you have right now) is to start throwing casts everywhere, like this:
Data<?> d = new Data("Hello");
String contents = (String)d.getData();
This is kind of a terrible idea, so let's go back to the drawing board.
If (ideally), you have all of the types you could ever need ahead of time (i.e. every Data is either a String or an Image or an Integer), then you can pretty easily (though it's a bit tedious) define a Sum type (aka a union if you're coming from C) of the different types of data you'll have to handle. As a class invariant, we assume that exactly one of the fields is non-null, and the rest are null. For this example I'll assume it can be either a String, an Image, or an Integer, but it's fairly simple to add or remove types from Data as necessary.
public class Data {
private Image imgData;
private String stringData;
private Integer intData;
public Data(Image img) {
this.imgData = img;
}
public Data(String stringData) {
this.stringData = stringData;
}
public Data(Integer intData) {
this.intData = intData;
}
public boolean isImage() {
return imageData != null;
}
public boolean isInteger() {
return intData != null;
}
public boolean isString() {
return stringData != null;
}
public Image asImage() {
if(! isImage()) throw new RuntimeException();
return imgData;
}
public Image asString() {
if(! isString()) throw new RuntimeException();
return stringData;
}
public Image asInt() {
if(! isInt()) throw new RuntimeException();
return intData;
}
}
One necessary side effect is that we cannot wrap null without causing exceptional behavior. Is this is desired, it isn't too difficult to modify the class to allow for it.
With this Data class, it's pretty easy to do if-else logic to parse it.
Data d = ....... //Get a data from somewhere
if(d.isImage()) {
Image img = d.asImage();
//...
} else if (d.isString()) {
String string = d.asString();
//...
} else if (d.isInteger()) {
Integer i = d.asInt();
//...
} else {
throw new RuntimeException("Illegal data " + d + " received");
}
If you call getData().getClass() you will get the class or type that was passed, which doesn't seem to me to be the same as an Object. You might not know what you are getting, but you can either find out or define a common interface for everything you might pass. You could for example, call toString() or getClass() on anything passed. Your question is that you are passing any conceivable object, so my question is what are you going to do with it? If you are going to serialize it into a database you don't need know anything about what type it is, otherwise you can test it or call a common interface.
public class PlayData {
class Msg {
private List<Data<?>> message = new ArrayList<Data<?>>();
public void addData(Data<?> datum) { message.add(datum); }
public void printTypes() { for ( Data<?> datum: message ) { System.out.println(datum.getData().getClass()); } }
}
class Data<T> {
private T value;
public Data(T value) { this.value = value; }
public T getData() { return value; }
}
class Listener {
public void receive(Msg msg) { msg.printTypes(); }
}
class Sender {
private Listener listener;
public Sender(Listener listener) { this.listener = listener; }
public void send(Msg msg) { listener.receive(msg); }
}
class MyPacket {
int i;
public MyPacket(int i) { this.i = i; }
}
public static void main(String[] args) throws Exception { new PlayData().run(); }
public void run() throws Exception {
Sender sender = new Sender(new Listener());
Msg msg = new Msg();
msg.addData(new Data<String>("testing") );
msg.addData(new Data<MyPacket>(new MyPacket(42)) );
sender.send(msg);
}
}
I have RESTeasy service. And have implemented simple error handling on methods using try catch and feel something is not very well with it. I've noticed try catch repetition on all my methods. So I want ask way how to avoid repetition (to reduce code size) of try catch but not lost functionality.
#Path("/rest")
#Logged
#Produces("application/json")
public class CounterRestService {
#POST
#Path("/create")
public CounterResponce create(#QueryParam("name") String name) {
try {
CounterService.getInstance().put(name);
return new CounterResponce();
} catch (Exception e){
return new CounterResponce("error", e.getMessage());
}
}
#POST
#Path("/insert")
public CounterResponce create(Counter counter) {
try {
CounterService.getInstance().put(counter);
return new CounterResponce();
} catch (Exception e){
return new CounterResponce("error", e.getMessage());
}
}
#DELETE
#Path("/delete")
public CounterResponce delete(#QueryParam("name") String name) {
try {
CounterService.getInstance().remove(name);
return new CounterResponce();
} catch (Exception e){
return new CounterResponce("error", e.getMessage());
}
}
... // other methods with some try catch pattern
response
public class CounterResponce {
private String status;
#JsonSerialize(include=Inclusion.NON_NULL)
private Object data;
public CounterResponce() {
this.status = "ok";
}
public CounterResponce(Object o) {
this.status = "ok";
this.data = o;
}
public CounterResponce(String status, Object o){
this.status = status;
this.data = o;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
exceptions source
public class CounterService {
private Map<String, StatisticCounter> counters = new HashMap<String, StatisticCounter>();
private static CounterService instance = null;
protected CounterService() {}
public static CounterService getInstance() {
if(instance == null) {
instance = new CounterService();
}
return instance;
}
public StatisticCounter get(String name){
StatisticCounter c = counters.get(name);
if(c == null)throw new IllegalArgumentException("Counter "+name+" not exist");
return c;
}
public void put(String name){
if(name==null)throw new IllegalArgumentException("null can`t be as name");
if(counters.get(name)!=null)throw new IllegalArgumentException("Counter "+name+" exist");
counters.put(name, new Counter(name));
}...
The comments in your question are pointing you in a good direction. Since the answers do not mention it, I'll summarize the general idea in this answer.
Extending WebApplicationException
JAX-RS allows to define direct mapping of Java exceptions to HTTP error responses. By extending WebApplicationException, you can create application specific exceptions that build a HTTP response with the status code and an optional message as the body of the response.
The following exception builds a HTTP response with the 404 status code:
public class CustomerNotFoundException extends WebApplicationException {
/**
* Create a HTTP 404 (Not Found) exception.
*/
public CustomerNotFoundException() {
super(Responses.notFound().build());
}
/**
* Create a HTTP 404 (Not Found) exception.
* #param message the String that is the entity of the 404 response.
*/
public CustomerNotFoundException(String message) {
super(Response.status(Responses.NOT_FOUND).
entity(message).type("text/plain").build());
}
}
WebApplicationException is a RuntimeException and doesn't need to the wrapped in a try-catch block or be declared in a throws clause:
#Path("customers/{customerId}")
public Customer findCustomer(#PathParam("customerId") Long customerId) {
Customer customer = customerService.find(customerId);
if (customer == null) {
throw new CustomerNotFoundException("Customer not found with ID " + customerId);
}
return customer;
}
Creating ExceptionMappers
In other cases it may not be appropriate to throw instances of WebApplicationException, or classes that extend WebApplicationException, and instead it may be preferable to map an existing exception to a response.
For such cases it is possible to use a custom exception mapping provider. The provider must implement the ExceptionMapper<E extends Throwable> interface. For example, the following maps the JAP EntityNotFoundException to a HTTP 404 response:
#Provider
public class EntityNotFoundExceptionMapper
implements ExceptionMapper<EntityNotFoundException> {
#Override
public Response toResponse(EntityNotFoundException ex) {
return Response.status(404).entity(ex.getMessage()).type("text/plain").build();
}
}
When an EntityNotFoundException is thrown, the toResponse(E) method of the EntityNotFoundExceptionMapper instance will be invoked.
The #Provider annotation declares that the class is of interest to the JAX-RS runtime. Such class may be added to the set of classes of the Application instance that is configured.
Introduce a private method such as "apply" which can take function as parameter if you use Java 8. This method will have the error handling and/or mapping, response mapping and response generation code centralized.
From create and delete methods, invoke this apply method and pass the desired counter operation you wish to perform as a lambda expression.
Consider this custom Exception class:
public class CustomException extends Exception {
private static final long serialVersionUID = 1L;
public static final int EXCEPTION1 = 1;
public static final int EXCEPTION2 = 2;
public static final int EXCEPTION3 = 3;
private int exceptionType;
private Throwable guiltyException;
public CustomException(String message, int type, Throwable cause){
super(message);
this.exceptionType = type;
this.guiltyException = cause;
}
public int getExceptionType(){
return this.exceptionType;
}
public Throwable getGuiltyException(){
return this.guiltyException;
}
}
And then assume there is somewhere a method such as this:
public SomeReturnType someMethod(SomeArgument argument) throws CustomException{
try{
someExceptionalMethodCall(); // Throws Exception1, Exception2, Exception3
} catch (Exception1 e1) {
throw new CustomException("Some info1", CustomException.EXCEPTION1, e1);
} catch (Exception2 e2) {
throw new CustomException("Some info2", CustomException.EXCEPTION2, e2);
} catch (Exception3 e3) {
throw new CustomException("Some info3", CustomException.EXCEPTION3, e3);
}
}
Is storing the Throwable just meaningless overhead I could avoid by adjusting the super call to Exception in the constructor of CustomException? Like this:
public CustomException(String message, int type, Throwable cause){
super(message, cause);
this.exceptionType = type;
}
Then I could get rid of guiltyException and getGuiltyException.
Is there any point in storing the Throwable cause in the CustomException class itself?
No, there's no reason to store the cause yourself when Throwable already has that facility. Your class should only introduce extra information, not duplicate fields which already have a meaning.
Aside from anything else, I would expect to be able to call getCause() and retrieve the original exception - whereas in your original code, I'd have to know that it's a CustomException, and call getGuiltyException(). One symptom of this is that any general purpose code logging the error won't see the cause in your current version - whereas it will if you use the standard approach to exception chaining.
You don't need to keep a reference to the exception cause since this can be set in the super(message, cause) constructor.