How to run a class which is converted from String? - java

I have stored some class names in a HashMap. When user provides the name, that particular class should run. How can I do this? Any help please.
I did like below, but i am getting class not found exception.
Map<String,String> ruleMap = new HashMap<String, String>();
ruleMap.put("1", "CalculatorTest");
ruleMap.put("2", "AreaTest")
JUnitCore junit = new JUnitCore();
and calling method is,
for (Map.Entry<String, String> entry : ruleMap.entrySet())
{
Class c = null;
if(selection.equals(entry.getKey()))
{
try
{
c = Class.forName(entry.getValue());
}
catch (Exception e)
{
e.printStackTrace();
}
junit.run(c);
break;
}
}
When I am calling like below it is working fine.
junit.run(CalculatorTest.class);

Use full-qualified-classnames instead of simple classnames!
Try to use:
ruleMap.put("1", CalculatorTest.class.getName());
ruleMap.put("2", AreaTest.class.getName());
Regards

junit.run(CalculatorTest.class); means junit.run(Package.CalculatorTest );
So junit.run(c) does not work .
for example ,
package cocat.test.kmt;
public static void main(String args[]) throws ClassNotFoundException {
String test =String.valueOf(Class.forName("cocat.test.kmt.Concat"));
System.out.println(test);
}
when run this code the below result is show,
class cocat.test.kmt.Concat

As Peter Rader and Peter Lawrey commented Class.forName() will take full name of the class.
In my case my code should be,
ruleMap.put("1", "package.CalculatorTest");
Thanks to both Peter`s.. :)

Related

Java : Crash without exception

I'm trying to debug some code that look like this :
class MyClass {
public void myMethod(HashMap<String, String> inputMap) {
try {
ConcurrentHashMap<String, String> cm = new ConcurrentHashMap<>();
cm.putAll(inputMap);
try {
for (Object key : cm.keySet()) {
cm.put(key.toString(), "");
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("After try catch");
} finally {
System.out.println("In finally");
}
}
}
By using the debugger in InteliJ I've figured out that this piece of code have an issue on the for loop line.
The execution pass from the for loop to the finally clause without passing in the catch clause neither the code after the try/catch.
The cm object isn't empty (there is around 30 elements in it).
I'm using java 7, System.getProperty("java.version") give 1.7.0_85
When I try to call the cm.keySet() mnually from the InteliJ debugger I have the following error message No such instance method: 'keySet'. But when I look at the javadoc of the ConcurentHashMap class this method should exists.
When I run cm.getClass().getDeclaredMethods() I see the method public java.util.Set java.util.concurrent.ConcurrentHashMap.keySet() in the methods list.
This code is not running on the main thread.
This don't display any error message in the console and I'm not able to catch an exception.
Does anyone have an idea of what could be the problem there? I've tried everything I could think of, and I'm out of options.
Edit problem fixed
The issue wasn't even in the code itself, it was that the compiler was updated from java 7 to java 8 without me noticing and without crashing during the compilation, while the java version that I use on my server was java 7. Since I didn't have the possibility to change neither the compiler version neither the version on the server, I've rewritten the code in another way so that it will work on both version.
It gives something like this :
class MyClass {
public void myMethod(HashMap<String, String> inputMap) {
try {
ConcurrentHashMap<String, String> cm = new ConcurrentHashMap<>();
cm.putAll(inputMap);
try {
Enumeration<String> keys = cm.keys();
while(keys.hasMoreElements()) {
String key = keys.nextElement();
cm.put(key, "");
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("After try catch");
} finally {
System.out.println("In finally");
}
}
}
Ps: Thank you, #cyberbrain, I wouldn't have figured this out without your advice on catching Throwable rather than Exception.
Try replacing Object with String
class MyClass {
public void myMethod(HashMap<String, String> inputMap) {
try {
ConcurrentHashMap<String, String> cm = new ConcurrentHashMap<>(inputMap);
try {
for (String key : cm.keySet()) {
cm.put(key, "");
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("After try catch");
} finally {
System.out.println("In finally");
}
}
}
You can also replace the entire for loop with the following:
cm.replaceAll((k, v) -> "");
edit: Realized lamdas wont work on JDK 1.7

Jmock/junit testing

If I have an SUT which handles an exception using a try/catch block, as follows:
public static void methodToBeTested() {
...
try {
desktop.browse(new URI("www.google.com"));
} catch (IOException e) {
//Display message to user and log out entry in app logs
}
...
}
Question is that should I test the condition from my unit tests that the IOException is thrown? (The method under test launches a URI in the default browser)
If yes, since I am not throwing the exception from this method, how do i unit test this condition when the desktop.browse() threw an IOException?
Any thoughts or suggestions? I am using JMock
Thanks!
Basically what you want to do is to
mockup Desktop and whenever you send a browse message to it (no matter what URI is used), instead of hitting that URI, it should throw an IOException.
I have used Jmock long time ago. JMock as far as I remember, has some limitations, for exmaple it does not provide a mechanism for mocking static methods. And I am not sure how easy it is to mock your browser class in jmock world.
However it is almost trivial to test this using jmockit, which supports all sorts of fancy mocking mechanisms (including static references, singletons etc). (I am mentioning jmockit because no matter what your browse class is, jmockit can mock it.)
Below is an excerpt from an example from their website:
package jmockit.tutorial.domain;
import org.apache.commons.mail.*;
import jmockit.tutorial.persistence.*;
import org.junit.*;
import mockit.*;
public final class MyBusinessService_ExpectationsAPI_Test
{
#Mocked(stubOutClassInitialization = true) final Database unused = null;
#Mocked SimpleEmail anyEmail;
#Test
public void doBusinessOperationXyz() throws Exception
{
final EntityX data = new EntityX(5, "abc", "abc#xpta.net");
final EntityX existingItem = new EntityX(1, "AX5", "someone#somewhere.com");
new Expectations() {{
(1) Database.find(withSubstring("select"), any);
result = existingItem; // automatically wrapped in a list of one item
}};
new MyBusinessService(data).doBusinessOperationXyz();
(2) new Verifications() {{ Database.persist(data); }};
(4) new Verifications() {{ email.send(); times = 1; }};
}
#Test(expected = EmailException.class)
public void doBusinessOperationXyzWithInvalidEmailAddress() throws Exception
{
new Expectations() {{
(3) email.addTo((String) withNotNull()); result = new EmailException();
}};
EntityX data = new EntityX(5, "abc", "someone#somewhere.com");
new MyBusinessService(data).doBusinessOperationXyz();
}
}
Above is the class under test and below is a the test which specifically tests (3) part of the above code. I think it is similar to what you are trying to do. Check it out please.
#Test(expected = EmailException.class)
public void doBusinessOperationXyzWithInvalidEmailAddress() throws Exception
{
new MockUp<Email>() {
#Mock
(3) Email addTo(String email) throws EmailException
{
assertNotNull(email);
throw new EmailException();
}
};
new MyBusinessService(data).doBusinessOperationXyz();
}
}
If you want to stick to jmock, it is fine. But then you need to give us more info about Desktop class and its browse method so that we can think about what we can do in jmock world.

Writing text files in java

So I know there are a lot of examples with writing textfiles, but I can't seem to get what is wrong with mine.
Here is the code I have so far
private void saveAddressBook() {
try {
PrintWriter out = new PrintWriter("filename.txt");
out.println(fullName);
out.close();
} catch(ValidationException e) {
e.printStackTrace();
}
}
I get an error on out.println(fullName); that says "fullName cannot be resolved to a variable"
Which makes no sense because I use it in other methods and classes. Not to mention it is public.
So what am I doing wrong?
Edit: fullName is declared right at the top of the class. I just didn't include it.
You didn't declare the variable fullName .
Try to declare and assign a value to the variable or give the String as the argument
out.println("my super string");
regards,
Your problem is that you have not defined the fullName variable.
Using out.println("FirstName LastName"); will work just fine, but if you want to pass the fullName variable as an agument to saveAddressBook that would look like:
private void saveAddressBook(String fullName) {
try {
PrintWriter out = new PrintWriter("filename.txt");
out.println(fullName);
out.close();
} catch(ValidationException e) {
e.printStackTrace();
}
}

Try / Catch in Constructor - Recommended Practice?

Something I've always been curious of
public class FileDataValidator {
private String[] lineData;
public FileDataValidator(String[] lineData){
this.lineData = lineData;
removeLeadingAndTrailingQuotes();
try
{
validateName();
validateAge();
validateTown();
}
catch(InvalidFormatException e)
{
e.printStackTrace();
}
}
//validation methods below all throwing InvalidFormatException
Is is not advisable to include the try/catch block within my Constructor?
I know I could have the Constructor throw the Exception back to the caller. What do you guys prefer in calling methods like I have done in Constructor? In the calling class would you prefer creating an instance of FileDataValidator and calling the methods there on that instance? Just interested to hear some feedback!
In the code you show, the validation problems don't communicate back to the code that is creating this object instance. That's probably not a GOOD THING.
Variation 1:
If you catch the exception inside the method/constructor, be sure to pass something back to the caller. You could put a field isValid that gets set to true if all works. That would look like this:
private boolean isValid = false;
public FileDataValidator(String[] lineData){
this.lineData = lineData;
removeLeadingAndTrailingQuotes();
try
{
validateName();
validateAge();
validateTown();
isValid = true;
}
catch(InvalidFormatException e)
{
isValid = false;
}
}
public boolean isValid() {
return isValid;
}
Variation 2:
Or you could let the exception or some other exception propagate to the caller. I have shown it as a non-checked exception but do whatever works according to your exception handling religion:
public FileDataValidator(String[] lineData){
this.lineData = lineData;
removeLeadingAndTrailingQuotes();
try
{
validateName();
validateAge();
validateTown();
}
catch(InvalidFormatException e)
{
throw new com.myco.myapp.errors.InvalidDataException(e.getMessage());
}
}
Variation 3:
The third method I want to mention has code like this. In the calling code you have to call the constructor and then call the build() function which will either work or not.
String[] lineData = readLineData();
FileDataValidator onePerson = new FileDataValidator();
try {
onePerson.build(lineData);
} catch (InvalidDataException e) {
// What to do it its bad?
}
Here is the class code:
public FileDataValidator() {
// maybe you need some code in here, maybe not
}
public void build(String[] lineData){
this.lineData = lineData;
removeLeadingAndTrailingQuotes();
try
{
validateName();
validateAge();
validateTown();
}
catch(InvalidFormatException e)
{
throw new com.myco.myapp.errors.InvalidDataException(e.getMessage());
}
}
Of course, the build() function could use a isValid() method that you call to see if its right but an exception seems the right way to me for the build function.
Variation 4:
The fourth method I want to mention is what I like best. It has code like this. In the calling code you have to call the constructor and then call the build() function which will either work or not.
This sort of follows the way JaxB and JaxRS work, which is a similar situation to what you have.
An external source of data - you have a file, they have an incoming message in XML or JSON format.
Code to build the objects - you have your code, they have their libraries of code working according the specifications in the various JSRs.
Validation is not tied to the building of the objects.
The calling code:
String[] lineData = readLineData();
Person onePerson = new Person();
FileDataUtilities util = new FileDataUtilities();
try {
util.build(onePerson, lineData);
util.validate(onePerson);
} catch (InvalidDataException e) {
// What to do it its bad?
}
Here is the class code where the data lives:
public class Person {
private Name name;
private Age age;
private Town town;
... lots more stuff here ...
}
And the utility code to build and validate:
public FileDataValidator() {
// maybe you need some code in here, maybe not
}
public void build(Person person, String[] lineData){
this.lineData = lineData;
removeLeadingAndTrailingQuotes();
setNameFromData(person);
setAgeFromData(person);
setTownFromData(person);
}
public boolean validate(Person person) {
try
{
validateName(person);
validateAge(person);
validateTown(person);
return true;
}
catch(InvalidFormatException e)
{
throw new com.myco.myapp.errors.InvalidDataException(e.getMessage());
}
}
You should consider the static factory pattern. Make your all-arguments constructor private. Provide a static FileDataValidator(args...) method. This accepts and validates all the arguments. If everything is fine, it can call the private constructor and return the newly created object. If anything fails, throw an Exception to inform the caller that it provided bad values.
I must also mention that this:
catch (Exception e) {
printSomeThing(e);
}
Is the deadliest antipattern you could do with Exceptions. Yes, you can read some error values on the command line, and then? The caller (who provided the bad values) doesn't get informed of the bad values, the program execution will continue.
My preference is for exceptions to be dealt with by the bit of code that knows how to deal with them. In this case I would assume that the bit of code creating a FileDataValidator knows what should happen if the file data is not valid, and the exceptions should be dealt with there (I am advocating propagating to the caller).
Whilst discussing best practice - the class name FileDataValidator smells to me. If the object you're creating stores file data then I would call it FileData - perhaps with a validate method? If you only want to validate your file data then a static method would suffice.

Using a returned string to call a method?

I have an ArrayList and wish to be able to call an index and use the returned string for a method call.
e.g.
stringList.get(2)();
Is there any way I could go about this?
So you want the returned String to be used as the name of the method to call?
You can do that using reflection, but I'd strongly discourage this.
Instead you will want to look into implementing a strategy pattern for example.
Yes, there is a way to use the returned string from the list for a method call.
As others users already pointed out, you need to use Reflection API. Can be complicated deal with that, depends on the particular scenario you are facing.
Just to show you the basic approach in a concrete but simplified example, I create this code. Copy it and play changing the index, and creating new methods with parameters after learn the basics of the API.
import java.lang.reflect.*;
import java.util.*;
public class DemoReflection {
public static void main(String[] args) {
List<String> myStringList = new ArrayList<String>();
myStringList.add(0, "foo");
myStringList.add(1, "printStr");
myStringList.add(2, "otherMethod");
myStringList.add(3, "stackoverflow");
int index = 3;
String methodName = myStringList.get(index);
try {
Class<?> c = Class.forName("DemoReflection");
Object obj = c.newInstance();
Method method = c.getDeclaredMethod(methodName, null);
method.invoke(obj, null);
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
public void stackoverflow() {
System.out.println("Stackoverflow rules!");
}
public void printStr() {
System.out.println("Method printStr invoked...");
}
}
First of call you can't call a method in java without an object to call it on. Is that in the list also.
It would be better to have a list of Runnable...
List<Runnable> runnables = ...
runnables.get(2).call();
If you have the object you need to call, and you want to use reflection (can be slow) then commons-beans can help make it simple. See http://commons.apache.org/beanutils
import org.apache.commons.beanutils.MethodUtils;
Object target = ...
List<String> methodNames = ...
MethodUtils.invokeMethod(target, methodNames.get(2), /*args*/ null);
To give better I'd advice I'd need to know more about the problem you are trying to solve.
One would have to use reflection. See http://tutorials.jenkov.com/java-reflection/methods.html.
Does the ArrayList have to contain Strings?
Otherwise you could populate it with java.lang.reflect.Method instances, and call Method.invoke() on the returned instance.
If I understand your needs, here is an example based on an interface; the list then contains implementations of the interface rather than method names:
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) throws Exception {
List<Action> actions = new ArrayList<Action>();
actions.add(new Action(){
public void execute() {
System.out.println("Action 0");
}});
actions.add(new Action(){
public void execute() {
System.out.println("Action 1");
}});
actions.get(0).execute();
actions.get(1).execute();
}
static interface Action{
void execute();
}
}
Or maybe polymorphism and a factory method would be a better idea. You'd have to circumscribe the methods you'll be able to call, but that wouldn't be a bad idea.
If you want the full Monty, and you're using Java 6, maybe you can create a JavaScript function object and invoke it with Rhino.
Or if you insist on making the idea work regardless of any obstacles, you could call out to a dynamic language like JRuby or Clojure, both of which are willing to eval() a String.
Or Jython or Groovy or...
In Java - no way. That's not a Java language feature. Your're hoping for something like
// NOT VALID JAVA
String myColoring = paintBlackOrWhite() ? "black" : "white";
myColoring(myBathroomWall);
// NOT VALID JAVA
Like others suggested, a pure technical solution would be using reflections: take the result string, find the corresponding method and invoke it. A technical solution could even be a map like
Map<String, java.lang.reflect.Method> myMethods;
and do something like
get("black").invoke(myObject, myParams);
but all of that is nice to know and you shouldn't use it unless forced or you have a concrete problem where even SO doesn't have a solution ;)

Categories

Resources