I have a question related to String.format in JAVA.
My HibernateDao Class is responsible for persisting entities and will throw an exception in case I have any constrain violation. The message contains a %s and will be used as a format in the upper layers, as I should be worried about types in this layer, thus can't identify what object I could not persist.
public Entity persistEntity(Entity entity) {
if (entity == null || StringUtils.isBlank(entity.getId()))
throw new InternalError(CANNOT_INSERT_NULL_ENTITY);
try {
getHibernateTemplate().save(entity);
} catch (DataAccessException e) {
if (e.getCause() instanceof ConstraintViolationException)
throw new HibernateDaoException("%s could not be persisted. Constraint violation.");
throw new HibernateDaoException(e);
}
return entity;
}
And then in my DaoHelper Class I will catch this exception and throw a new one, with a formatted message.
//Correct Code
public Entity create(Entity object) throws MyException {
try {
return this.hibernateDao.persistEntity(object);
} catch (HibernateDaoException he) {
String format = he.getMessage();
throw new MyException(String.format(format,object.getClass().getSimpleName()));
}
}
My question is, why I cannot directly call the he.getMessage() in my String.format method?? And must use a 'tmp' variable instead... It just won't substitute the %s from the string.
//What I wished to do, but I cant.
public Entity create(Entity object) throws MyException {
try {
return this.hibernateDao.persistEntity(object);
} catch (HibernateDaoException he) {
throw new MyException(String.format(he.getMessage(),object.getClass().getSimpleName()));
}
}
Thx in advance.
This should be closed, as the intended behavior is working. As #Kal and #highlycaffeinated commented, calling the getMessage() directly does work, something must have happened with my build and did not update correctly. However the messages do appear correctly now.
Thanks for the quick answers :)
Related
So I have these methods:
private List<ClientRepresentation> toClientRepresentation(String json) {
try {
return objectMapper.readValue(json, new TypeReference<List<ClientRepresentation>>() {
});
} catch (JsonProcessingException e) {
throw new RuntimeException("Could not parse json.");
}
}
private List<RoleRepresentation> toRoleRepresentation(String json) {
try {
return objectMapper.readValue(json, new TypeReference<List<RoleRepresentation>>() {
});
} catch (JsonProcessingException e) {
throw new RuntimeException("Could not parse json.");
}
}
private List<UserRepresentation> toUserRepresentation(String json) {
try {
return objectMapper.readValue(userJson, new TypeReference<List<UserRepresentation>>() {
});
} catch (JsonProcessingException e) {
throw new RuntimeException("Could not parse json.");
}
}
You can see these are similar... Would like to have one method for these... Something like this:
private List<T> toObjectsList(String json, Class classToConvert) {
try {
return objectMapper.readValue(json, new TypeReference<List<classToConvert>>() {
});
} catch (JsonProcessingException e) {
throw new RuntimeException("Could not parse json.");
}
}
Is it possible? How?
Thanks in advance.
Note first that Class<?> can be used to convey only type-parameter-less constructs. Thus, something like List<String> cannot be conveyed with it (only 'List' - any and all lists, unparameterized - that is the only thing Class can convey). If you ever want toObjectsList to return something like a List<Map<String, Object>> you are dead in the water on this: The entire setup fundamentally can't do it. So, first consider whether this is a good idea: You are handicapping yourself, that your toObjectsList method cannot ever return lists of type-argsed types. Presumably, if you're willing to document this and sign up to tacle such needs by not using toObjectsList and writing a custom readValue-based method instead, you're good to go.
Assuming you're on board with this restriction, the question boils down to: How does one construct an STT (Super-Type-Token, that TypeReference thing with the brackets after it) dynamically?
This should be doable, using the TypeFactory class.
For example, constructParametricType(List.class, List.class, classToConvert);.
We then need to address some other errors in your code:
That exception handling is deplorable. You're tossing away all the useful info, and replacing it with entirely useless information. Don't write a catch block that fails to address the issue, unless that catch block preserves all information. Also, by convention exception messages do not end in punctuation.
You are using a <T> in these methods, but you need to declare that T exists, first.
Class, itself, is parameterized.
This gets us to:
private <T> List<T> toObjectsList(String json, Class<T> classToConvert) {
JavaType typeTarget = TypeFactory.defaultInstance()
.constructParametricType(List.class, List.class, classToConvert);
try {
return objectMapper.readValue(json, typeTarget);
} catch (JsonProcessingException e) {
// pass the original exception along as cause, preserving info.
throw new RuntimeException("Could not parse json", e);
}
}
(You may have to cast to List<T>, but I don't think it'll be needed due to some dubious hackery on jackson's part).
im currently working in a complete generic scenario in which i map a json as string to a dto class. That works fine with my function mapJsonToDto but im trying to make it more generic so that the developer who uses this function can also specify what exception to be thrown. So they can catch as they like. With this i avoid catching an IOException. Letting the function handle everything.
public class MapperUtils {
public <T extends Throwable> Object mapJsonToDto(Class<?> dtoClass, String jsonDto, T exceptionToThrow) throws IOException {
Object dto = null;
try {
dto = new ObjectMapper().readValue(jsonDto, dtoClass);
} catch (IOException e) {
throw new exceptionToThrow();
}
return dto;
}
}
I cannot understand how to pass an exception class instance to a function and throwing that specific as well.
Instead of passing the exception to throw (which would then have a completely wrong stack trace), I think you'd want a function that converts an exception from one type to another:
public <T extends Throwable, D> D mapJsonToDto(Class<D> dtoClass, String json, Function<IOException, T> exceptionMapper) throws T {
try {
return new ObjectMapper().readValue(json, dtoClass);
// if readValue doesn't do the casting right, try:
return dtoClass.cast(new ObjectMapper().readValue(json, dtoClass);
} catch (IOException e) {
throw exceptionMapper.apply(e);
}
}
And an example:
Person p = mapJsonToDto(Person.class, "{name: \"Joe\"}",
e -> new IllegalArgumentException("malformed JSON", e));
As a general rule, though, this seems like boneheaded design. If you find the IOException overly general, then you can't handwave the problem away by allowing the caller to provide a no doubt similarly overly general mapper. The only way out for a caller is to do a deep dive on the exception and write, I dunno, an if/elseif block with a ton of levels to it to try to ascertain the real problem e.g. via analysing the message, which is all sorts of ugly.
Either you don't care about that level of detail and you should therefore just stick with IOException (what point is there adding code and pointless layers of indirection?), or you do care and this isn't good enough; you'd want to design a better error system. Except, that's not your job, that'd be ObjectMapper.readValue's job. Which is why the IOException it throws should probably just be sent on unmolested.
Your example is nearly done.
I changed only the throws Type to T and throw the given exception.
public <T extends Throwable> Object mapJsonToDto(Class<?> dtoClass, String jsonDto, T exceptionToThrow) throws T {
Object dto = null;
try {
dto = new ObjectMapper().readValue(jsonDto, dtoClass);
} catch (IOException e) {
throw exceptionToThrow;
}
return dto;
}
Call: mapJsonToDto(String.class, "helo", new IllegalStateException());
I can’t understand how to handle the following error:
In the class CustomerService I delete the customer by id, and if such an id does not exist, then an error must be thrown! How can you do without an if else construct?
CustomerService:
// Delete customer
public void deleteCustomer(Long id){
Customer customer = customerRepository.getByIdAndUserRole(id, "customer");
customerRepository.delete(customer);
}
CustomerController:
// DELETE MAPPING
//
// Delete customer with ID
#DeleteMapping("/customers/{id}")
void deleteCustomer(#PathVariable Long id) {
customerService.deleteCustomer(id);
}
Try to use Controller Advice. Whenever a exception occur it will directly handled by the handler. No if/else or try/catch blocks will be required.
1) Create a class CustomerControllerHandler, annotate with #ControllerAdvice.
2) Now create methods with arguments having the type of Exception.
3) The methods will return the JSON/POJO/void you want.
4) Annotate the methods with #ExceptionHandler(Exception.class) and
#ResponseStatus(HttpStatus.BAD_REQUEST),
#ControllerAdvice
public class CustomerControllerHandler {
#ExceptionHandler(Exception.class)
#ResponseStatus(HttpStatus.BAD_REQUEST)
public void processException(Exception ex) {
}
}
You can try using this instead. It's the deleteById method for a CrudRepository (hope you're using that) and it throws IllegalArgumentException if it can't find a customer.
I assumed that with "error" you meant "exception" and then in the controller you can surround with a try-catch block like that:
try{
customerService.deleteCustomer(id);
} catch (IllegalArgumentException e) {
log.error("No customer id exists!", e);
// if you have no logger, then use System.out.println() at least
}
If you wanted instead to return an error to the caller, then change the data type from void to HttpResponse<String> and when catching an exception you can return HttpResponse<>("No customer exists with that id!", HTTP.BAD_REQUEST). Now the caller will get a 400 - bad request.
A nicer approach would be to catch the exception in the service itself and return a boolean to the controller (true if customer is deleted and false if couldn't delete / couldn't find one).
if you want to throw error then you will have to check a condition, that is there will be an if statement, but not necessarily an else is needed.
For instance, you can check response of delete and throw error according to below one.
if (deleteCount == 0) {
//throw error here
}
I have been searching online and researching in some books, but the examples given are limited and I still have some doubts in user-defined exception.
Using the following codes as an example:
//Conventional way of writing user-defined exception
class IdException extends Exception
{
public IdException(String s)
{
super(s);
}
}
class Product
{
String id = new String();
public Product(String _id) throws IdException
{
id = _id;
//Check format of id
if (id.length() < 5)
throw(new IdException(_id));
}
}
It seems that the conventional way of writing a user-defined exception is almost always the same. In the constructor of the user-defined exception, we always call super(msg). This triggers a question in me: If most exceptions are implemented this way, what difference are there between all these exceptions?
For example, I can have multiple user-defined exceptions, but all seems to do the same thing without any differences. (There is no implementation in these exceptions, what makes them work?)
Example:
class IdException extends Exception
{
public IdException(String s)
{
super(s);
}
}
class NameException extends Exception
{
public NameException(String s)
{
super(s);
}
}
class ItemException extends Exception
{
public ItemException(String s)
{
super(s);
}
}
QUE: So shouldn't we (for example) implement the checking of id inside the exception class? If not all exception classes just seem to do the same thing (or not doing anything).
Example of implementing the check in an Exception:
class IdException extends Exception {
public IdException(String s)
{
super(s);
//Can we either place the if-statements here to check format of id ?
}
//Or here ?
}
Ideally you should not implement your business logic inside Exception. Exception tells information about exceptional behaviour, And in Custom Exception you can customise that information.
Find the best practice to write Custom Exception.
We have so many Exceptions already defined in java. All do the same thing : to notify user about the problem in code.
Now suppose we have only one Exception, then How we can what error occurs when the exception is thrown. After all, name matters a lot.
To take your example Exceptions, I would create a more elaborate message by formatting the data provided:
public IdException(String id, String detail) {
super(String.format("The id \"%s\" is invalid: %s", id, detail));
}
throw new IdException(_id, "Id too short.");
This way there is no real logic in the IdException class other than providing the given value (id) and a detail message together in the e.getMessage() String so debugging and logging is easy to read and the code itself is also straightforward:
There is something wrong with the Id _id, namely it is too short. Thus we throw it back at the caller.
Also, when you throw different types of Exceptions in a code, it allows caller code to handle each Exception type differently:
try {
getItem(id, name);
} catch (IdException ex) {
fail(ex.getMessage()); // "The Id is bogus, I don't know what you want from me."
} catch (NameException ex) {
warn(ex.getMessage()); // "The name doesn't match the Id, but here's the Item for that Id anyways"
} catch (ItemException ex) {
fail("Duh! I reported to the dev, something happened");
emailToAdmin(ex.getMessage()); // "The Item has some inconsistent data in the DB"
}
class MyException extends Exception{
int x;
MyException(int y) {
x=y;
}
public String toString(){
return ("Exception Number = "+x) ;
}
}
public class JavaException{
public static void main(String args[]){
try{
throw new MyException(45);
}
catch(MyException e){
System.out.println(e) ;
}
}
}
output: Exception Number = 45
I need to check if an exception is caused by some database problem. I receive an Exception and check if its cause contains the "ORA" string and return that (something like "ORA-00001"). The problem here is that the exception I receive is nested inside other exceptions, so if I don't find out if it's an oracle exception, I have to check into the cause of that exception and so on.
Is there a cleaner way to do this? Is there a way to know the first cause (the deep-nested exception) of a given exception?
My current code looks like this:
private String getErrorOracle(Throwable e){
final String ORACLE = "ORA";
if (e.getCause() != null && e.getCause().toString().contains(ORACLE)){
return e.getCause().toString();
} else if(e.getCause() != null){
return getErrorOracle(e.getCause());
} else {
return null;
}
}
In the interests of not reinventing the wheel, if you're using Apache Commons Lang, then look at ExceptionUtils.getRootCause().
Is it worth including a library just for that? Maybe not. But if you already have it on your classpath, it's there for you, and note that it does some things that a 'naive' implementation might not do (e.g. deal with cycles in the cause chain... ugh!)
If you are already on Guava than Throwables.getRootCause() comes to the rescue.
Just traverse the exception chain until you get to an exception with no cause, and then just return that message, if you want the last one.
Your function will only get the first cause, if there is one.
You may want to look at finding the first cause in your package though, as the actual deepest one may be an oracle exception, which is helpful, but unless you can see where you created the problem, you will have a hard time fixing it.
Probably a bit overkill for your usage but I think it is cleaner (and reusable)
interface ThrowablePredicate {
boolean accept(Throwable t);
}
public OracleErrorThrowablePredicate implements ThrowablePredicate {
private static final ORA_ERR = "ORA";
public boolean accept(Throwable t) {
return t.toString().contains(ORA_ERR);
}
}
public class CauseFinder {
private ThrowablePredicate predicate;
public CauseFinder(ThrowablePredicate predicate) {
this.predicate = predicate;
}
Throwable findCause(Throwable t) {
Throwable cause = t.getCause();
return cause == null ? null
: predicate.accept(cause) ? cause : findCause(cause)
}
}
// Your method
private String getErrorOracle(Throwable e){
return new CauseFinder(new OracleErrorThrowablePredicate()).findCause(e);
}
I think that any error that is thrown by oracle will be wrapped in a SQLException (somebody please correct me if wrong). Once you have accessed the SQLException you should be able to call
getErrorCode()
Retrieves the vendor-specific exception code for this SQLException object.
Let me know if this works as I have never tried it :-)
Karl
You could improve your code checking for SQLException
import java.sql.SQLException;
private static final String ORACLE = "ORA";
public String doHandle(Throwable t) {
if (t.getClass().isAssignableFrom(SQLException.class)) {
SQLException e = (SQLException) t;
int errCode = e.getErrorCode();
String state = e.getSQLState();
String msg = e.getMessage();
if (msg.contains(ORACLE)) {
return msg;
}
} else {
if (t.getCause() != null) {
return this.doHandle(t.getCause());
}
}
return "";
}
Also, I think in Oracle "errCode" contains the number associated to ORA-nnnn
In my Spring Boot project for getRootCause IDEA suggest 3 static import:
Spring Core: org.springframework.core.NestedExceptionUtils.getRootCause
Jackson: com.fasterxml.jackson.databind.util.ClassUtil.getRootCause
Guava (Swagger transitive) com.google.common.base.Throwables.getRootCause
Most smart (with cycle check) is Spring NestedExceptionUtils.getRootCause.
But, if your excetion has no cause, method returns null.
In my case it is wrong, so I've done:
#NonNull
public static Throwable getRootCause(#NonNull Throwable t) {
Throwable rootCause = NestedExceptionUtils.getRootCause(t);
return rootCause != null ? rootCause : t;
}
ExceptionUtils.getRootCause(), and Throwables.getRootCause() returns null if the cause of the exception being passed is null.The following method will return the original throwable if an throwable without a cause is being passed as the input parameter.
/**
* #return the root cause of a given throwable.
* If throwable without a cause is being passed, the original throwable will be returned
*/
public static Throwable getRootCause(#NonNull final Throwable throwable) {
List<Throwable> throwableList = ExceptionUtils.getThrowableList(throwable);
return throwableList.get(throwableList.size() - 1);
}
One line solution using core Java API:
try {
i = 1 / 0;
} catch (ArithmeticException e) {
System.out.println(new ArithmeticException().initCause(e).getCause());
}
One more solution below works as well:
try {
i = 1 / 0;
} catch (ArithmeticException e) {
System.out.println(new Exception().initCause(e).getCause());
}
Both of them will print
java.lang.ArithmeticException: / by zero
I want to add Kotlin extension functions to get root causes:
fun Throwable.rootCause(): Throwable {
return if (cause == null) this else cause!!.rootCause()
}
//Return null if first cause is null
fun Throwable.optRootCause(): Throwable? {
return if (cause == null) null else cause!!.rootCause()
}
Or this one if need to find a cause inside the throwable chain at any points:
fun <T : Throwable> Throwable.isOrContainsCauseOfType(clazz: KClass<T>): Throwable? {
return when {
clazz.isInstance(this) -> this //remove if you want to exclude [this]
cause == null -> null
clazz.isInstance(cause) -> cause
else -> cause!!.isOrContainsCauseOfType(clazz)
}
}
If the exception being thrown is always going to be of a specific type, like OracleException, you can catch just that exception.
For example:
try {
...
} catch(OracleException oe) {
...
}
This would only apply if there are specific Oracle exceptions being thrown. I don't know much about Oracle, so before attempting this you will probably want to find out if that's what's happening.
on 28-01-2015 , i have unable to solve my problem with any of the above solution, so my recommendation is to use :
e.getMessage().toString();
Ps: i am using it on android.