Exceptions handler for getenv() - java

How can I handle NullPointerException and SecurityException for that kind of line code:
public final static String PROJECT_DIR = System.getenv().get("HOME") + "/Projects/MyTestProject";
It will be sufficient to just wrap it with try/catch? If so how I can differ it will be NullPointerException or SecurityException?
Also are there any best practices to have it stored in properties if getenv() is not available or something else?

Initialize the final static String in the class initializer. Throw a new exception describing the problem (not set, not allowed). For example:
public final static String PROJECT_DIR;
static {
try {
Map<String, String> env = System.getenv();
if (!env.contains("HOME")) {
throw new AssertionError("HOME not set as environment variable");
}
PROJECT_DIR = env.get("HOME") + "/Projects/MyTestProject";
} catch (SecurityException e) {
throw new AssertionError("Security policy doesn't allow access to system environment", e);
}
}

This would throw both NullPointerExceptions and SecurityExceptions:
public static void main(String[] args) throws Exception {
System.out.println("System.getenv("HOME") = ");
System.out.println(System.getenv("HOME"));

Related

Java NegativeTest private method with Reflection to catch custom ApplicationException

So I'm testing a AccountService class with a mocked databaselayer.
In this AccountService class there is a private method that checks the input received from UI according to a regex.
The positive test I wrote is working fine:
#Test
public void testEmailPatroonCorrect() throws Exception{
//Correcte emails
List<String> emails = new ArrayList<>();
emails.add("user#domain.com");
emails.add("user#domain.co.in");
emails.add("user.name#domain.com");
emails.add("user_name#domain.com");
emails.add("username#yahoo.corporate.in");
Class<AccountService> foo = AccountService.class;
Method method = foo.getDeclaredMethod("checkEmailPatroon", String.class);
method.setAccessible(true);
assertThatCode(() -> {
for(String email : emails){
method.invoke(AccountService,email);
}}).doesNotThrowAnyException();
}
However for the negative test (a list with wrong email patterns) even with only one object in the list for simplicity
#Test
public void testEmailPatroonFout() throws Exception{
//Verkeerde emailpatronen
List<String> emails = new ArrayList<>();
emails.add(".username#yahoo.com");
Class<AccountService> foo = AccountService.class;
Method method = foo.getDeclaredMethod("checkEmailPatroon", String.class);
method.setAccessible(true);
assertThatThrownBy(()->{
for(String email : emails){
method.invoke(AccountService,email);
}
}).isInstanceOf(ApplicationException.class).hasMessage(ApplicationExceptionType.ONGELDIGE_EMAIL.getMsg());
}
The exception thrown during test is: java.lang.reflect.InvocationTargetException. In the application the ApplicationException gets caught just fine.
Question is how can I write a proper test for a list of wrong email patterns? (without using #VisibleForTesting functionality since it's a school project).
Many thanks!
The InvocationTargetException wraps the exception thrown within the reflectively invoked method. So you may catch the InvocationTargetException and rethrow its cause, but I’d put that into a utility method, like
public interface TestMethod<D,A> {
void invoke(D d, A a) throws Throwable;
}
static <D,A> TestMethod<D,A> method(
Class<D> declarer, String name, Class<A> argType) throws ReflectiveOperationException {
Method method = declarer.getDeclaredMethod(name, argType);
method.setAccessible(true);
return (d,a) -> {
try {
method.invoke(d, a);
} catch(InvocationTargetException ex) {
throw ex.getTargetException();
}
};
}
which you can use like
#Test
public void testEmailPatroonFout() throws Exception{
//Verkeerde emailpatronen
List<String> emails = new ArrayList<>();
emails.add(".username#yahoo.com");
TestMethod<AccountService, String> method
= method(AccountService.class, "checkEmailPatroon", String.class);
assertThatThrownBy(() -> {
for(String email : emails){
method.invoke(AccountService, email);
}
}).isInstanceOf(ApplicationException.class)
.hasMessage(ApplicationExceptionType.ONGELDIGE_EMAIL.getMsg());
}
The shape of the TestMethod interface allows the alternative implementation like
static <D,A> TestMethod<D,A> method(
Class<D> declarer, String name, Class<A> argType) throws ReflectiveOperationException {
Method method = declarer.getDeclaredMethod(name, argType);
method.setAccessible(true);
return MethodHandleProxies.asInterfaceInstance(
TestMethod.class, MethodHandles.lookup().unreflect(method));
}
Thanks to Holger I was able to write a working test for it's purpose.
#Test
public void testEmailPatroonFoutLoop() throws Throwable {
//Verkeerde emailpatronen
List<String> wrongEmails = new ArrayList<>();
wrongEmails.add(".username#yahoo.com");
wrongEmails.add("username#yahoo.com.");
wrongEmails.add("usernameyahoo.com");
wrongEmails.add("username#yahoo.c");
wrongEmails.add("use..rname#yahoo.com");
Class<AccountService> foo = AccountService.class;
Method method = foo.getDeclaredMethod("checkEmailPatroon", String.class);
method.setAccessible(true);
int countedWrongEmails = 0;
for(String email : wrongEmails){
try{
method.invoke(accServ,email);
}
catch (InvocationTargetException ie){
Exception e = (Exception) ie.getTargetException();
if(e.getMessage().equals(ApplicationExceptionType.ONGELDIGE_EMAIL.getMsg())){
countedWrongEmails++;
}
}
}
assertThat(countedWrongEmails).isEqualTo(wrongEmails.size());
}
Although I see the benefits and elegance of writing a TestMethod interface, I however do not yet possess the knowledge to grasp it's complexity. So I will stick to this test that I'll be able to explain on the verbal exam.

Testing a method by overriding a private class variable as an initial step before refactoring

What is the best way of writing a unit test for a method, such as my setProperties (see below), that uses a private configuration variable (config). I tried but failed to override it using reflection and Makito, but without success. I realize that changing the design to make the code easier to test is best, but I want to created some unit tests before I refactor the code.
public class MainClass {
private final java.lang.String config = "app.properties";
public TestClass() {
try {
setProperties();
} catch (Exception e) {
e.printStackTrace();
}
}
public void setProperties() throws Exception {
try {
InputStream input = new BufferedInputStream(new FileInputStream(config));
..
..
} catch (Exception exception) {
throw exception;
}
}
}
Do refactor a tiny bit by extracting a method with a parameter that takes an input stream. Call this new method (probably package-protected) from the old one. Write tests against the new method. Then do more refactorings.
This is an indication of a broken design; don't hard-code things like this. Better yet, determine what the appropriate responsibility for this class is, and, in decreasing order of preference:
pass in an object with the configuration properties, strongly typed
pass in a Map with the configuration properties
pass in an InputStream for the properties file
As File objects are never available from a jar, you shouldn't ever make interfaces like this more specific than InputStream or Reader, so that you can always pass in streams from your jar classpath.
So you can use Properties class in Java for this. Please have a look at this code.
public class PropertyUtil {
private static Properties prop;
private static Logger logger = Logger.getLogger(PropertyUtil.class);
private PropertyUtil() {
}
public void setProperty() {
String filePath = System.getenv("JAVA_HOME") + "/lib" + "/my_file.properties";
prop = new Properties();
try (InputStream input = new FileInputStream(filePath)) {
prop.load(input);
} catch (IOException ex) {
logger.error("Error while reading property file " + ex);
}
}
public static String getProperty(String key) {
if (prop.containsKey(key)) {
return prop.getProperty(key);
} else {
return null;
}
}
public static <T> T getProperty(String key, Class<T> claz) {
if (claz.getName().equals(Integer.class.getName())) {
return claz.cast(Integer.parseInt(prop.getProperty(key)));
}
if (claz.getName().equals(Long.class.getName())) {
return claz.cast(Long.parseLong(prop.getProperty(key)));
}
if (claz.getName().equals(Boolean.class.getName())) {
return claz.cast(Boolean.parseBoolean(prop.getProperty(key)));
}
if (claz.getName().equals(Double.class.getName())) {
return claz.cast(Double.parseDouble(prop.getProperty(key)));
}
if (claz.getName().equals(String.class.getName())) {
return claz.cast(prop.getProperty(key));
}
return null;
}

Class body - Call function to instantiate variable (unhandled exception type)

I'm having a small issue with my java code.
public class test {
static char[] pass = getMac(); // getting error on this line
public static char[] getMac() throws UnknownHostException
{
...code...
return x;
}
}
I am already throwing the exception in the method but i'm getting the error on this line too :
static char[] pass = getMac(); // getting error on this line
unhandled Exception Type : unknownHostException
is there any way to fix this ?
Thanks
I have tried :
try
{
static char[] pass = getMac();
}
catch (UnknownHostException e)
{
.....
}
but it doesn't work in the main class .
I am already throwing the exception in the method...
Right. That's the problem. By saying that the method throws that exception, you're forcing the calling code to handle it. Java's class initialization code isn't going to handle it for you, so you're getting an unhandled exception error.
Either handle it in the method, or defer initializing that static field until a time when you can handle it*. Note that static initializer blocks are allowed to include flow logic, so that's also an option.
Handling it in the method:
public static char[] getMac()
{
try {
// ...
return x;
}
catch (UnknownHostException e) {
// Appropriate handling
return null; // Or whatever's appropriate
}
}
Using a static initializer block:
public class test {
static char[] pass;
static {
try {
// ...
pass = x;
}
catch (UnknownHostException e) {
// Appropriate handling
pass = null; // Or whatever's appropriate
}
}
}

Suggestion for improving cli wrapper over Apache Commons CLI

I have following cli wrapper:
public class CLIUtil
{
// some private variable and other methods
public CLIUtil(final String[] args, final Options commandLineOptions) throws ParseException
{
Validate.notEmpty(args);
Validate.notNull(commandLineOptions);
this.commandLineOptions = commandLineOptions;
this.command = this.parser.parse(this.commandLineOptions, args);
}
public void printHelp(final String executableName)
{
Validate.notEmpty(executableName);
final HelpFormatter formatter = new HelpFormatter();
formatter.printHelp(executableName, this.commandLineOptions);
}
}
Which have following problems:
As we are throwing exception in constructor:
if args as null. There is no way to printHelp.
if args are invalid. There is no way to printHelp.
I am thinking of following solution:
Solution 1:
public CLIUtil(final String executableName, final Options commandLineOptions) throws ParseException
{
Validate.notNull(commandLineOptions);
this.commandLineOptions = commandLineOptions;
this.executableName = executableName;
}
public void parseArgs(final String[] args) throws ParseException
{
Validate.notEmpty(args);
this.command = this.parser.parse(this.commandLineOptions, args);
}
Problem with this solution is:
User need to call set after constructor. so we are letting client to control the flow.
Solution 2:
public CLIUtil(final String executableName, String[] args, final Options commandLineOptions) throws ParseException
{
if (null == args) {
// show help and throw illegal arg
}
Validate.notNull(commandLineOptions);
this.commandLineOptions = commandLineOptions;
this.executableName = executableName;
try {
this.command = this.parser.parse(this.commandLineOptions, args);
} catch (Parse...) {
// catch exception and show error and printhelp followed by
// throw same exception
}
}
Problem with this solution is:
1) Random placement of validation rule.
Do you have a suggestion which solution is better or suggested improvement?

When objects in Java are partially initialized ( an exception occurs in the constructor )

I've heard that it is possible to write some code like this
SomeClass obj = null;
try {
obj = new SomeClass();
} catch ( Exception e ) {
...
}
...
if ( obj != null ) { // here it holds true
...
}
Can somebody please explain, is that possible at all and under what conditions if we assume that constructor SomeClass may throw an Exception?
Another example:
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.junit.Test;
public class Sample{
static class A {
public static A s;
public A(Collection c) {
c.add(this);
s = this;
throw new RuntimeException();
}
}
#Test
public void testResource() throws Exception {
List l = new ArrayList();
A a = null;
try {
a = new A(l);
fail("Oops");
} catch (Throwable e) {
}
assertTrue(l.size() == 1);
assertNull(a);
assertNotNull(A.s);
assertNotNull(l.get(0));
}
}
First you declare and initialize a variable.
SomeClass obj = null;
In the following lines you (1) create a new instance and (2) store the reference.
try {
obj = new SomeClass();
} catch ( Exception e ) {
...
}
Now we assume, the instantiation (Step 1) fails and throws an exception: the JVM will continue in the next catch block that handles that exception. So step 2 will not be executed and the variable will keep its actual state.
Now is is possible that an instance has been initialized partially. Honestly, I don't know, that's JVM internal. But as nothing holds a reference to this partially initialized instance, it will be gc'd on the next occasion.
It's quite possible.
I'm not sure I understand your question though, you've answered it yourself: if the constructor throws an exception, obj could be null.
You can certainly write code like that, and it will compile and run just fine. But there will never be a case where obj is "partially initialized". Either it will be, or it won't be. Specifically, if this line throws an Exception:
obj = new SomeClass();
Then it is as if that line was never executed, as far as the value of obj is concerned. You initialize obj to null prior to that line, so if an exception is thrown then obj will still be null. In that case the program will not go into the if block at the end.
Or, if an exception is not thrown, then obj will no longer be null, and the code inside of the final if block will be executed.
It is perfectly possible; look closer: if the constructor throws an exception, obj will still be null.
If the SomeClass constructor throws an Exception obj will be NULL.
For me the object is null even after calling constructor:
public static void main(String[] args) {
TestCls cls = null;
try {
cls = new TestCls("");
} catch (Exception e) {
e.printStackTrace();
}
if(cls == null)
System.out.println("hi");
}
public TestCls(String str) throws Exception{
throw new Exception();
}
Output:-
java.lang.Exception
hi
at TestCls.<init>(TestCls.java:57)
at TestCls.main(TestCls.java:48)
Conclusion: If the class constructor throws an Exception then the obj will be NULL.
The constructor could throw an Exception, just like any other call in Java could. For instance it may throw a NullPointerException if trying to call a method on a null reference. Consider the following example:
public class ConstructionTest {
static ConstructionTest obj;
public ConstructionTest() {
String s = null;
s.hashCode();
}
public static void main(String[] args) {
try {
obj = new ConstructionTest();
} catch ( Exception e ) {
System.err.println(e);
}
if ( obj != null ) {
System.err.println("Not Null");
} else {
System.err.println("Is Null");
}
}
}
As s is null in the Constructor a NullPointerException is thrown, so "Is Null" gets printed. There is no concept of a "partially constructed Object" - when you use new in Java it either works and you get the newly instantiated Object back or it doesn't work and you get the Exception.

Categories

Resources