How to handle NoSuchElementException and NullPointerException in stream java 8 - java

I got an issue to handle NoSuchElementException and NullPointerEception.
I tried to handle NoSuchElementException error from this code:
public Item shop(ItemShopParam itemShopParam) {
String orderNumber = itemShopParam.getOrderNumber();
Shipment shipment = shipmentService.findByNumber(orderNumber);
Item item = findBySku(shipment.getId(), itemShopParam.getItemSku());
Job job = item.getShipment().getJobs().stream().filter(j -> j.getType().equals(Job.Type.RANGER)).findFirst().get();
checkJobState(job);
private void checkJobState(Job job) {
if (job.getState() == Job.State.INITIAL)
throw new JobNotStartedException();
if (job.getState() == Job.State.FINISHED)
throw new JobAlreadyFinishedException();
}
by replace get() with Optional().orElse(null). But, it returned another error exception NullPointerException. I know why this happened because checkJobState check null value of job.
The enum state:
public enum State {
INITIAL(0),
STARTED(1),
LAST_ITEM_PICKED(2),
FINALIZING(3),
ACCEPTED(4),
DELIVERING(5),
FOUND_ADDRESS(6),
FINISHED(7),
FAILED(8);
What is the best practice to avoid NoSuchElementException without return NullPointerException?

You can use Optional.isPresent() check:
Optional<Job> maybeJob = item.getShipment().getJobs().stream().filter(j -> j.getType().equals(Job.Type.RANGER)).findFirst();
if(maybeJob.isPresent()) {
checkJobState(job);
}
or even better an ifPresent():
Optional<Job> maybeJob = item.getShipment().getJobs().stream().filter(j -> j.getType().equals(Job.Type.RANGER)).findFirst().ifPresent(job -> checkJobState(job));

you can put the instructions to get the job from itemShopParam in a java Function, in this way you can easy test it.
Then use try catch to get any unexpected behaviour and specialise it in your exception inside a catch block.
The exception fired could be checked, if extends Throwable or Runtime if you wants manage it optionally.
//FUNCTION CLASS
class FromItemShopParamToJob implements Function<ItemShopParam,Item>
{
#Override
public Item apply(ItemShopParam itemShopParam) {
Item i=new Item();
//instructions to get job
return i;
}
}
class FromItemToJob implements Function<Item,Job> {
#Override
public Job apply(Item item) {
Job j=new Job();
//instructions to get job
return j;
}
}
//YOUR EXCEPTION CLASS
public class JobNotFoundException extends RuntimeException{
public JobNotFoundException(String message) {
super(message);
}
}
//YOUR METHOD
public void getJobFromItemShop(ItemShopParam param){
try {
Item item = new FromItemShopParamToJob().apply(param);
Job j=new FromItemToJob().apply(item);
} catch (Exception e){
System.out.print(e);
throw new JobNotFoundException(e.toString());
}
}

Related

How can I parameterize a generic method so as not to repeat the structure of the tests?

I have a Spring Boot project in which I am adding the below Test of some of the classes.
#Test
void documentException() {
assertThrows(DocumentException.class, () -> {
try {
throw new DocumentException();
} catch (Exception ex) {
assertEquals("Error converting document format", ex.getMessage());
assertEquals(417 /* EXPECTATION_FAILED */, ex.getHttpStatus());
assertEquals(ErrorCodes.DOCUMENT_ERROR, ex.getCode());
throw ex;
}
});
}
#Test
void maxUserException() {
assertThrows(MaxUserException.class, () -> {
try {
Integer maxUsers = 5;
throw new MaxUserException(maxUsers);
} catch (Exception ex) {
Integer maxUsers = 5;
assertEquals("Excedido el número máximo de "+ maxUsers +" dispositivos", ex.getMessage());
assertEquals(403 /* FORBIDDEN */, ex.getHttpStatus());
assertEquals(ErrorCodes.MAX_USERS_DEVICES, ex.getCode());
throw ex;
}
});
}
#Test
void docFormatException() {
assertThrows(DocFormatException.class, () -> {
try {
throw new DocFormatException();
} catch (Exception ex) {
assertEquals("Document format", ex.getMessage());
assertEquals(415 /* UNSUPPORTED_MEDIA_TYPE */, ex.getHttpStatus());
assertEquals(ErrorCodes.DOCUMENT_ERROR, ex.getCode());
throw ex;
}
});
}
For each class I use the same method.
Would there be any way to create a class with a #Test and call it for each class? So as not to have to create such a large structure for each of the classes.
What I want is to make a general method and apply it to each of the classes. So as not to have to repeat the same structure for all classes.
Well, answering directly to your question and using your actual examples - if you want to avoid code duplication then you can use some utility method.
Assuming your exceptions are subtypes of your custom class or implement the same interface which have methods getHttpStatus and getCode. Let's say parent class or interface has name CustomException.
Create a new class, for example TestUtils and define the method which can be reused is your tests, something like that (idk what type getCode() should return, so I assume it's String)
public class TestUtils {
public static void testException(CustomException exception, String message,
String errorCode, int httpStatus) {
assertThrows(exception.getClass(), () -> {
try {
throw exception;
} catch (CustomException ex) {
assertEquals(message, ex.getMessage());
assertEquals(httpStatus, ex.getHttpStatus());
assertEquals(errorCode, ex.getCode());
throw ex;
}
});
}
}
Then your test methods can be simplified:
#Test
void documentException() {
TestUtils.testException(new DocumentException(),
"Error converting document format",
417,
ErrorCodes.DOCUMENT_ERROR);
}
maxUserException() a bit trickier but still works:
#Test
void maxUserException() {
int maxUsers = 5;
MaxUserException exception = new MaxUserException(maxUsers);
String message = "Excedido el número máximo de "+ maxUsers +" dispositivos";
TestUtils.testException(exception, message, ErrorCodes.MAX_USERS_DEVICES, 403);
}
Hope it can be helpful. However it's worth mentioning - if it's your real test code and it's written exactly like this, then those methods attempt to test that your custom exceptions are created with correct default parameters (that's all) and in that case, test methods can be simplified as they are overcomplicated right now.
Your example test methods seems bit complicated, but it worth mentioning there in JUnit5 there are annotations to handle parameterized test.
You should look into these documents:
Java doc for #ParameterizedTest , #ValueSource , #CsvSource.
here is a sample example of how to parameterized a test:
#ParameterizedTest
#CsvSource(value = {
// input and expected output separated by :
"test:test",
"tEst:test",
"Java:java"
}, delimiter = ':')
void toLowerCase_ShouldGenerateTheExpectedLowercaseValue(String input, String expected) {
String actualValue = input.toLowerCase();
assertEquals(expected, actualValue);
}
Have a look in this Guide to JUnit 5 Parameterized Tests.

How to call a method in parent class inside of Lambda function in Java?

I was trying to write the following piece of code, but the error happened on line return super.getAge("Jack");
It showed "The method getAge() is undefined for the type Object". I guess the "super" keyword is not identified here.
Does anyone have any suggestions that how to fix this error? Thanks so much!
public class Parent {
public int getAge(String name) {
System.out.println("Get the age of the parent.");
return 40;
}
}
public class Child extends Parent {
#Override
public int getAge(String name) {
Future<Integer> ageFuture = null;
#Qualifier("XXX")
private ExecutorService executorService;
try {
ageFuture = executorService.submit(new Callable<Integer>() {
public int call() throws Exception {
return super.getAge("Jack");
}
});
} catch (Exception e) {
logger.error(" ", e);
}
return 10;
}
}
Try Parent.super.getAge("jack"), though I don't think that will work.
If not, then your only option is to make a bridge method:
public class Child extends Parent {
private int superGetAge(String name) {
return super.getAge(name);
}
#Override
public int getAge(String name) {
.... return superGetAge("jack");
}
}
Because you are using new Callable() which is instantiating a new class then super.getAge("jack") is referring to a non-existant method.
Instead switch to lambda definition which can reference super.getAge("Jack") directly:
Callable<Integer> call = () -> super.getAge("Jack");
try {
ageFuture = executorService.submit(call);
}
// etc...
or shorter:
ageFuture = executorService.submit(() -> super.getAge("Jack"));
Youre defining a new class on-the-fly with "new Callable {...} "
That class is inherited from Object.
You could try defining the Parent getAge() as a static method and call it with
Parent.getAge("Jack");

creating subclass instances from base class

I have a number of typed exceptions which all share the same characteristic: they hold a status (int) field which is always non-zero. The code typically checks for a status variable and if that is non-zero throws the corresponding exception (depending on the context). I.e.:
if (status != 0) throw new AStatusException(status);
... // other context
if (status != 0) throw new BStatusException(status);
... // other context
if (status != 0) throw new CStatusException(status);
Mostly out of curiusity I thought I might implement this common functionality in a static method throwIfNotZero of a base class StatusException and have the various A, B, CStatusException classes all inherit that class. This would hopefully allow me to write code like this:
AStatusException.throwIfNonZero(status);
... // other context
BStatusException.throwIfNonZero(status);
... // other context
CStatusException.throwIfNonZero(status);
Sadly, the closest I got is the code I append at the end of the post, which is not very satisfactory. Is there a better way to do it, perhaps without using Reflection and / or avoiding the requirement to pass the class instance which appears redundant (see 'usage')?
Base Exception
import java.lang.reflect.InvocationTargetException;
public class StatusException extends Exception {
public int status;
public StatusException (int status) {
this.status = status;
}
public static <T extends StatusException> void raiseIfNotZero(Class<T> klass, int code) throws T{
try {
if (code != 0) throw klass.getConstructor(Integer.TYPE).newInstance(code);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
usage:
AStatusException.raiseIfNotZero(AStatusException.class, status);
BStatusException.raiseIfNotZero(BStatusException.class, status);
You can overload function raiseIfNotZero() in the super class StatusException.
And call it like this
StatusException.raiseIfNotZero(AStatusException.class, status);
StatusException.raiseIfNotZero(BStatusException.class, status);
public static int final STATUS_EXCEPTION_A=1;
public static int final STATUS_EXCEPTION_A=2;
raiseIfNotZero(int type, int status)
{
switch(type)
{ case STATUS_EXCEPTION_A: throw new AStatusException(); break;
case STATUS_EXCEPTION_B: throw new BStatusException(); break;
...
}
}

How can I customize custom exceptions in Java?

This is the original exception code
public class NoValueForParametarException extends Exception {
private Exception nestedException;
private int errorCode;
public NoValueForParametarException(String message) {
super(message);
}
public NoValueForParametarException(Exception ex,String message) {
super(message);
this.nestedException = ex;
}
public NoValueForParametarException(String message, int errorCode) {
super(message);
this.setErrorCode(errorCode);
}
public Exception getNestedException() {
return this.nestedException;
}
public void setNestedException(Exception nestedException) {
this.nestedException = nestedException;
}
public int getErrorCode() {
return this.errorCode;
}
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
public String toString() {
StringBuffer errorMsg = new StringBuffer();
errorMsg.append("[" + super.getMessage() + "]:");
errorMsg.append((this.nestedException != null) ? ("\n[Nested exception]:" + this.nestedException):"");
return errorMsg.toString();
}
}
and this is the new one
public class NoValueForParametarWebServiceException extends NoValueForParametarException {
public NoValueForParametarWebServiceException(String message) {
super(message);
}
public NoValueForParametarWebServiceException(Exception ex,String message) {
super(message);
this.setNestedException(ex);
}
public NoValueForParametarWebServiceException(String message, int errorCode) {
super(message);
this.setErrorCode(errorCode);
}
public String toString() {
StringBuffer errorMsg = new StringBuffer();
errorMsg.append(super.getMessage());
errorMsg.append((this.getNestedException() != null) ? ("\n[Nested exception]:" + this.getNestedException()):"");
return errorMsg.toString();
}
}
All I need is to change the part of the toString() method so instead of errorMsg.append("[" + super.getMessage() + "]:"); I have errorMsg.append(super.getMessage());. The problem appears when, in a method, the original is thrown because the catch block set to NoValueForParametarWebServiceException doesn't catch the original. I know I could catch the original and just re-throw the new one (which would also be satisfying), but I was wondering if there is another way.
EDIT: It seems what I need is unclear, so to be more clear:
The program throws NoValueForParametarException. I want to catch it but use the toString() method of NoValueForParametarWebServiceException (that is the sole reason of creating the new class) because I need the output format of the new version without changing the old.
I don't see any reason to subclass your first exception. Also, if you get rid of the nestedException instance variable and use java.lang.Throwable's cause instead, you don't have to mess with overriding toString and you can delete most of this code.
The problem appears when, in a method,
the original is thrown because the
catch block set to
'NoValueForParametarWebServiceException'
doesn't catch the original. I know I
could catch the original and just
re-throw the new one (which would also
be satisfying)
You don't need to re throw child exception.
Just catch parent exception in this case.
try{
//your code
}catch(NoValueForParametarException e){
//whatever handling you need to do. suppose you call toString() method
System.out.println(e.toString());
}
In above case catch block will be executed if any of your exceptions are thrown
(NoValueForParametarException or NoValueForParametarWebServiceException).
And depending upon which exception is thrown its toString() method will be called. (Simple inheritance rule) i.e.
NoValueForParametarException is
thrown toString defined in
NoValueForParametarException class
will be called for instance.
And if
NoValueForParametarWebServiceException
is thrown then overriden toString
method from
NoValueForParametarWebServiceException
will be called.
Some tutorials related to exceptions:
http://download.oracle.com/javase/tutorial/essential/exceptions/index.html
http://tutorials.jenkov.com/java-exception-handling/index.html
Hope this helps.

Try Catch Block in Java

So I'm given this code and I have to create an Exception and then use a Try/Catch Block to catch it. I've already made the Exception, at the bottom of the code. But I've never used a Try/Catch Block before and am not sure how to implement it.
The Exception is if a rank that isn't listed under the enum is entered. I need to use a toString with the caught exception as well, but I'm pretty sure I can figure that one out.
package pracapp4;
import java.util.Scanner;
public class Staff extends Employee
{
enum Title
{
DEPARTMENT_HEAD, DIRECTOR, DEAN, VICE_CHANCELLOR, CHANCELLOR
}
private Title title;
public Staff()
{
super();
title = Title.DEPARTMENT_HEAD;
}
public Staff(String firstName, String lastName, int salary, Title title)
{
super(firstName, lastName, salary);
this.title = title;
}
#Override
public String toString()
{
return super.toString() + "\n\tTitle: " + title;
}
#Override
public void display()
{
System.out.println("<<Staff>>" + this);
}
#Override
public void input(Scanner in)
{
super.input(in);
if (in.hasNext())
{
this.title = Enum.valueOf(Title.class, in.next());
}
}
class InvalidRankException extends Exception
{
public InvalidRankException()
{
super ("Unknown Rank Name: ");
}
}
}
You don't need that exception. The moment you add your Title enum as the type you pass into the Staff constructor it's impossible to provide a value that's not in the enum. You'll never get an invalid title. That's the whole point of enum.
UPDATE: A little code review is an order here.
Your default constructor is rather odd. You can be department head without a name or salary? A call to "this" is appropriate here, and better default values are in order.
Whole numbers only for salary - OK. No units? USD? Euro?
Can salary be negative? Does that make sense? (Note to self: Don't work there.)
Why do you need both toString and display? What is display overriding? I'd recommend ditching display and sticking with toString.
Your input method makes no sense whatsoever.
Why is that Exception an inner class?
try/catch are used to catch exceptions thrown by methods inside the try clause. If the methods inside the try does not throw any exceptions then the try/catch will not makes sense.
Right now you made your exception but there is no method that throws your exception.
This is simple example on how to use exceptions:
public class myTest
{
public void myMethod() throws InvalidRankException
{
//Logic here
if(something_is_wrong)
{
throw new InvalidRankException("Invalid Rank on myMethod due ...");
}
}
class InvalidRankException extends Exception
{
public InvalidRankException()
{
super ("Unknown Rank Name: ");
}
}
Now, whenever you run MyTest.myMethod() the compiler will require a try/catch surrounding that call.
MyTest test = new MyTest();
try
{
test.myMethod();
}
catch(InvalidRankException ex)
{
//Something went wrong
}
Not exactly sure what you're trying to do, but try-catch blocks work like this:
try{
throw new Exception("Example exception");
}
catch(Exception e){
System.out.println( "Exception caught: " + e.getMessage() );
}
You'll also have to modify the method that you are trying so that it throws the Exception you're looking for:
public void doSomething(String blah) throws Exception
Catching an exception is as simple as:
try{
//Some code that throws MyExceptionClass
}catch(MyException e){
//Some code that handles the exception e
}
Throwing an exception is as simple as:
throw new MyException(some, parameters, of, your choice);
If your exception doesn't descend from RuntimeException then you must declare the the method throws it:
public void myExceptionCausingMethod() throws MyException{
//Method code
}
The try/catch statement encloses some code and is used to handle errors and exceptions that might occur in that code.
public void input(Scanner in) throws InvalidRankException {
super.input(in);
if (in.hasNext()) {
try {
title = Enum.valueOf(Title.class, in.next());
} catch(InvalidRankException ire) {
//You've hit the exception, code in here how to handle the situation
}
}
}
There's two issues here:
Enum won't return an invalid rank/title
InvalidRankException doesn't test for anything to cause it to fire.

Categories