Is there a way to take an argument in a callable method? - java

I have created a piece of code which takes an IP address (from main method in another class) and then loops through a range of IP addresses pinging each one as it goes. I have a GUI front end on this and it was crashing (hence why I've done the multithreading. My problem is I can no longer take the IP address as an argument in my ping code as its callable. I've searched all over for this and cant seem to find a way to get round this. Is there a way for a callable method to take arguments? If not is there any other way to accomplish what I'm trying to do?
sample of my code:
public class doPing implements Callable<String>{
public String call() throws Exception{
String pingOutput = null;
//gets IP address and places into new IP object
InetAddress IPAddress = InetAddress.getByName(IPtoPing);
//finds if IP is reachable or not. a timeout timer of 3000 milliseconds is set.
//Results can vary depending on permissions so cmd method of doing this has also been added as backup
boolean reachable = IPAddress.isReachable(1400);
if (reachable){
pingOutput = IPtoPing + " is reachable.\n";
}else{
//runs ping command once on the IP address in CMD
Process ping = Runtime.getRuntime().exec("ping " + IPtoPing + " -n 1 -w 300");
//reads input from command line
BufferedReader in = new BufferedReader(new InputStreamReader(ping.getInputStream()));
String line;
int lineCount = 0;
while ((line = in.readLine()) != null) {
//increase line count to find part of command prompt output that we want
lineCount++;
//when line count is 3 print result
if (lineCount == 3){
pingOutput = "Ping to " + IPtoPing + ": " + line + "\n";
}
}
}
return pingOutput;
}
}
IPtoPing used to be the argument that was taken.

You can't pass it as the argument to call() because the method signature doesn't allow it.
However, you can pass the necessary information as a constructor argument; e.g.
public class DoPing implements Callable<String>{
private final String ipToPing;
public DoPing(String ipToPing) {
this.ipToPing = ipToPing;
}
public String call() throws SomeException {
InetAddress ipAddress = InetAddress.getByName(ipToPing);
....
}
}
(I've corrected a couple of egregious code style violations!!)
There are ways to eliminate some of the "boilerplate" coding in the above (see some of the other answers). In this case we are talking about 4 lines of code (in a ~40 line class), so I am not convinced that it is worth the effort. (But hey, it is your code.)
Alternatively, you could:
declare DoPing as an inner class (or a lambda) and have it refer to a final ipToPing in the enclosing scope, or
add a setIpToPing(String ipToPing) method.
(The last allows a DoPing object to be reused, but the downside is that you will need to synchronize to access it thread-safely.)

Adding to Jarle's answer -- in case you create Callable as instance of anonymous class, you can use final field outside of anonymous class for passing data into the instance:
final int arg = 64;
executor.submit(new Callable<Integer>() {
public Integer call() throws Exception {
return arg * 2;
}
});

You can't pass arguments to call() because the method signature doesn't allow it but here is at least one way to work around that by
defining an abstract class that wraps/implements Callable and
implementing a setter to "inject" a result into call()
Define an abstract class:
import java.util.concurrent.Callable;
public abstract class Callback<T> implements Callable<Void> {
T result;
void setResult (T result) {
this.result = result;
}
public abstract Void call ();
}
Define the method that should fire the callback:
public void iWillFireTheCallback (Callback callback) {
// You could also specify the signature like so:
// Callback<Type of result> callback
// make some information ("the result")
// available to the callback function:
callback.setResult("Some result");
// fire the callback:
callback.call();
}
In the place where you want to call iWillFireTheCallback:
Define the callback function (even possible inside methods):
class MyCallback extends Callback {
#Override
public Void call () {
// this is the actual callback function
// the result variable is available right away:
Log.d("Callback", "The result is: " + result);
return null;
}
}
And then call iWillFireTheCallback while passing in the callback:
iWillFireTheCallback(new MyCallback());

When you create the doPing-class (should be captial letter in class name), send in the ip-address in the constructor. Use this ip-address in the call-method.

Put some (final) fields in your doPing class, and a constructor that initializes them, then pass the values you want to use in call() to the constructor of doPing:
public class DoPing implements Callable<String> {
private final String ipToPing;
public DoPing(String ip) {
this.ipToPing = ip;
}
public String call() {
// use ipToPing
}
}

I know it is super-late to answer this, considering it is more than 8 years old but active 15 days(!) ago, I feel this will still help someone using Java 8 and above.
PS, it is simply a syntactic sugar of Victor Sorokin's answer possible through lambdas.
public static Callable<String> generateCallableWithArg(final String input) {
return () -> {
Thread.sleep(5000); // someExpensiveOperationHere
return "Return Value of " + input; //input can be used here
};
}
Also, we can write a static helper method that can convert a Function to Callable.
public class CallableGenerator {
public static <T,V> Callable<V> getCallableFromFunction(Function<T, V> function, T input) {
return () -> function.apply(input);
}
}
This can be used as
Callable<Integer> iAmCallable = CallableGenerator.getCallableFromFunction(i1 -> i1 * 2, 3);

You have to defien a property such as ipAddress and its accessor method. and passing its value in constructor or by setter method. In doPing class use ipAddress property.
class DoPing/* In java all classes start with capital letter */implements Callable<String>
{
private String ipAddress;
public String getIpAddress()
{
return ipAddress;
}
public void setIpAddress(String ipAddress)
{
this.ipAddress = ipAddress;
}
/*
* Counstructor
*/
public DoPing(String ipAddress )
{
this.ipAddress = ipAddress;
}
#Override
public String call() throws Exception
{
// your logic
}
}

It is not always possible to make reference to (effectively) final variable to use its value as "argument", but you can make comfy general solution by yourself. First define this functional interface:
#FunctionalInteface
interface CallableFunction<T, R> {
public abstract R call(T arg) throws Exception;
public static <T, R> Callable<R> callable(CallableFunction<T, R> cf, T arg) {
return () -> cf.call(arg);
}
}
This functional interface provides static method callable that creates a Callable instance, which simply calls call(T) with provided argument (of type T). Then you need you DoPing class to implement CallableFunction like this:
public class DoPing implements CallableFunction<String, String> {
#Override
public String call(final String ipToPing) throws Exception {
final var ipAddress = InetAddress.getByName(ipToPing);
final var reachable = ipAddress.isReachable(1400);
String pingOutput = null;
if (reachable) {
pingOutput = ipToPing + " is reachable.\n";
}
else {
final var ping = Runtime.getRuntime().exec("ping " + ipToPing + " -n 1 -w 300");
try (var in = new BufferedReader(new InputStreamReader(ping.getInputStream()))) {
String line;
for (int lineCount = 1; (line = in.readLine()) != null; ++lineCount) {
if (lineCount == 3) {
pingOutput = "Ping to " + ipToPing + ": " + line + "\n";
break;
}
}
}
}
return pingOutput;
}
Here we changed call signature to accept String argument and also now it implements CallableFunction and not Callable as before. Other changes are minor, but it's worth mentioning, that we prevented resource leak with use of try-with-resource on BufferedReader and also break has been added to input collecting loop (change from while to for) to terminate as quickly, as possible.
Now you can use the code e.g. like this:
final var ping = CallableFunction.callable(new DoPing(), "127.0.0.1");
final var task = new FutureTask<>(ping);
new Thread(task).start();
System.out.println(task.get(20, TimeUnit.SECONDS));
You can also reuse CallableFunction in other cases, when you needed it.

Related

Passing method in other method Java

I want to make a simple program to compare how long time takes rewrite and print out collection of Strings by `for loop`, `foreach` or `stream`. String is sentence where it replaces "i" by "y". In my case I made `count()` where I set to count `stream()` method but I want to make universal measuring method. But i dont know how to do it... It should works like: in Main class is `counter(forLoop);` It should call `forLoop();` from Method class `counter(forEach);` It should call `forEach();` from Metrod class`counter(stream);` It should call ` stream();` From Method class IDont know how to pass method as a parameter
I have class where are those metods:
import java.util.*;
import java.util.stream.*;
public class Methods {
private List<String> sentence = new ArrayList<>();
private String oldLetter = "i";
private String newLetter = "y";
private String methodType;
public String getMethodType() {
return methodType;
}
//making a collection with String
public void setSizeOfCollection(int size){
for (int i = 0; i < size; i++) {
sentence.add("Siti Zbinek plitce zvikal sirovi pelinek.");
}
}
public void forLoop(){
methodType = "For loop";
for (int i = 0; i < sentence.size(); i++) {
for (int j = 0; j < sentence.size(); j++) {
String replaceLetters = sentence.get(j);
replaceLetters = replaceLetters.replaceAll(oldLetter, newLetter);
sentence.set(j, replaceLetters);
}
System.out.println(sentence.get(i));
}
}
public void forEach(){
methodType = "For each";
String replacedLetters = "";
for(String oneLine: sentence){
for(String originalLetters: sentence){
replacedLetters = originalLetters.replaceAll(oldLetter,newLetter);
}
System.out.println(replacedLetters);
}
}
public void stream(){
methodType= "Stream";
sentence.stream()
.map(e->e.replaceAll(oldLetter,newLetter))
.collect(Collectors.toList())
.forEach(System.out::println);
}
}
This is count() that works fine, but only for method stream(). In comment is my imagine how it should be. But I dont know how it do by Java :(
import org.apache.commons.lang.time.*;
public class Counter {
private Methods methods;
private String methodType;
private StopWatch stopWatch = new StopWatch();
long timeTaken = 0;
//here should be something like any method as a parameter XXX xxx
// public void count(Methods methods XXX xxx)
public void count(Methods methods){
stopWatch.start();
// here sould be something what call any function by your choice, not only stream()
// methods.xxx;
methods.stream();
stopWatch.stop();
timeTaken= stopWatch.getTime();
System.out.println(methods.getMethodType()+" takes "+ timeTaken + " ms." );
}
}
And finally Main class
public class Main {
public static void main(String[] args) {
Methods methods = new Methods();
Counter counter = new Counter();
methods.setSizeOfCollection(10000);
counter.count(methods);
//here should be finally three times method, with different parameters:
// counter.count(methods, forEach);
// counter.count(methods, forLoop);
// counter.count(methods, stream);
}
}
Any advice please?
All your methods have the signature void(). Consequently, a reference to each method can be stored in a Runnable instance.
public void count(final Runnable method) {
stopWatch.start();
method.run();
stopWatch.stop();
timeTaken= stopWatch.getTime();
System.out.println(methods.getMethodType()+" takes "+ timeTaken + " ms.");
}
And then call as:
final Methods methods = new Methods();
final Counter counter = new Counter();
methods.setSizeOfCollection(10000);
counter.count(methods::stream); // or count(() -> methods.stream());
counter.count(methods::forEach); // count(() -> methods.forEach());
counter.count(methods::loop); // count(() -> methods.loop());
To be able to use method refs or lambdas, you need to have at least Java 8. For earlier Java versions, you would need to implement Runnable with an anonymous class, e.g.
counter.count(new Runnable() {
#Override public void run() { methods.stream(); }
});
or look up the methods by name via Reflection, but Reflection is usually the slowest option.
PS. Note however that your way of measuring method execution times is flawed; see How do I write a correct micro-benchmark in Java? for directions. This answer only explains the part of passing "methods" to another method.
you could pass the method name as a string and look for it with reflexion.

Java: Easy way of passing a method as a parameter [duplicate]

I need to find the caller of a method. Is it possible using stacktrace or reflection?
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace()
According to the Javadocs:
The last element of the array represents the bottom of the stack, which is the least recent method invocation in the sequence.
A StackTraceElement has getClassName(), getFileName(), getLineNumber() and getMethodName().
You will have to experiment to determine which index you want
(probably stackTraceElements[1] or [2]).
Note: if you are using Java 9 or later you should use StackWalker.getCallerClass() as described in Ali Dehghani's answer.
The comparison of different methods below is mostly interesting for historical reason.
An alternative solution can be found in a comment to this request for enhancement.
It uses the getClassContext() method of a custom SecurityManager and seems to be faster than the stack trace method.
The following program tests the speed of the different suggested methods (the most interesting bit is in the inner class SecurityManagerMethod):
/**
* Test the speed of various methods for getting the caller class name
*/
public class TestGetCallerClassName {
/**
* Abstract class for testing different methods of getting the caller class name
*/
private static abstract class GetCallerClassNameMethod {
public abstract String getCallerClassName(int callStackDepth);
public abstract String getMethodName();
}
/**
* Uses the internal Reflection class
*/
private static class ReflectionMethod extends GetCallerClassNameMethod {
public String getCallerClassName(int callStackDepth) {
return sun.reflect.Reflection.getCallerClass(callStackDepth).getName();
}
public String getMethodName() {
return "Reflection";
}
}
/**
* Get a stack trace from the current thread
*/
private static class ThreadStackTraceMethod extends GetCallerClassNameMethod {
public String getCallerClassName(int callStackDepth) {
return Thread.currentThread().getStackTrace()[callStackDepth].getClassName();
}
public String getMethodName() {
return "Current Thread StackTrace";
}
}
/**
* Get a stack trace from a new Throwable
*/
private static class ThrowableStackTraceMethod extends GetCallerClassNameMethod {
public String getCallerClassName(int callStackDepth) {
return new Throwable().getStackTrace()[callStackDepth].getClassName();
}
public String getMethodName() {
return "Throwable StackTrace";
}
}
/**
* Use the SecurityManager.getClassContext()
*/
private static class SecurityManagerMethod extends GetCallerClassNameMethod {
public String getCallerClassName(int callStackDepth) {
return mySecurityManager.getCallerClassName(callStackDepth);
}
public String getMethodName() {
return "SecurityManager";
}
/**
* A custom security manager that exposes the getClassContext() information
*/
static class MySecurityManager extends SecurityManager {
public String getCallerClassName(int callStackDepth) {
return getClassContext()[callStackDepth].getName();
}
}
private final static MySecurityManager mySecurityManager =
new MySecurityManager();
}
/**
* Test all four methods
*/
public static void main(String[] args) {
testMethod(new ReflectionMethod());
testMethod(new ThreadStackTraceMethod());
testMethod(new ThrowableStackTraceMethod());
testMethod(new SecurityManagerMethod());
}
private static void testMethod(GetCallerClassNameMethod method) {
long startTime = System.nanoTime();
String className = null;
for (int i = 0; i < 1000000; i++) {
className = method.getCallerClassName(2);
}
printElapsedTime(method.getMethodName(), startTime);
}
private static void printElapsedTime(String title, long startTime) {
System.out.println(title + ": " + ((double)(System.nanoTime() - startTime))/1000000 + " ms.");
}
}
An example of the output from my 2.4 GHz Intel Core 2 Duo MacBook running Java 1.6.0_17:
Reflection: 10.195 ms.
Current Thread StackTrace: 5886.964 ms.
Throwable StackTrace: 4700.073 ms.
SecurityManager: 1046.804 ms.
The internal Reflection method is much faster than the others. Getting a stack trace from a newly created Throwable is faster than getting it from the current Thread. And among the non-internal ways of finding the caller class the custom SecurityManager seems to be the fastest.
Update
As lyomi points out in this comment the sun.reflect.Reflection.getCallerClass() method has been disabled by default in Java 7 update 40 and removed completely in Java 8. Read more about this in this issue in the Java bug database.
Update 2
As zammbi has found, Oracle was forced to back out of the change that removed the sun.reflect.Reflection.getCallerClass(). It is still available in Java 8 (but it is deprecated).
Update 3
3 years after: Update on timing with current JVM.
> java -version
java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b132)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b70, mixed mode)
> java TestGetCallerClassName
Reflection: 0.194s.
Current Thread StackTrace: 3.887s.
Throwable StackTrace: 3.173s.
SecurityManager: 0.565s.
Java 9 - JEP 259: Stack-Walking API
JEP 259 provides an efficient standard API for stack walking that allows easy filtering of, and lazy access to, the information in stack traces. Before Stack-Walking API, common ways of accessing stack frames were:
Throwable::getStackTrace and Thread::getStackTrace return an array of
StackTraceElement objects, which contain the class name and method
name of each stack-trace element.
SecurityManager::getClassContext is a protected method, which allows a
SecurityManager subclass to access the class context.
JDK-internal sun.reflect.Reflection::getCallerClass method which you shouldn't use anyway
Using these APIs are usually inefficient:
These APIs require the VM to eagerly capture a snapshot of the entire
stack, and they return information representing the entire stack.
There is no way to avoid the cost of examining all the frames if the
caller is only interested in the top few frames on the stack.
In order to find the immediate caller's class, first obtain a StackWalker:
StackWalker walker = StackWalker
.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
Then either call the getCallerClass():
Class<?> callerClass = walker.getCallerClass();
or walk the StackFrames and get the first preceding StackFrame:
walker.walk(frames -> frames
.map(StackWalker.StackFrame::getDeclaringClass)
.skip(1)
.findFirst());
Sounds like you're trying to avoid passing a reference to this into the method. Passing this is way better than finding the caller through the current stack trace. Refactoring to a more OO design is even better. You shouldn't need to know the caller. Pass a callback object if necessary.
Oneliner:
Thread.currentThread().getStackTrace()[2].getMethodName()
Note that you might need to replace the 2 with 1.
This method does the same thing but a little more simply and possibly a little more performant and in the event you are using reflection, it skips those frames automatically. The only issue is it may not be present in non-Sun JVMs, although it is included in the runtime classes of JRockit 1.4-->1.6. (Point is, it is not a public class).
sun.reflect.Reflection
/** Returns the class of the method <code>realFramesToSkip</code>
frames up the stack (zero-based), ignoring frames associated
with java.lang.reflect.Method.invoke() and its implementation.
The first frame is that associated with this method, so
<code>getCallerClass(0)</code> returns the Class object for
sun.reflect.Reflection. Frames associated with
java.lang.reflect.Method.invoke() and its implementation are
completely ignored and do not count toward the number of "real"
frames skipped. */
public static native Class getCallerClass(int realFramesToSkip);
As far as what the realFramesToSkip value should be, the Sun 1.5 and 1.6 VM versions of java.lang.System, there is a package protected method called getCallerClass() which calls sun.reflect.Reflection.getCallerClass(3), but in my helper utility class I used 4 since there is the added frame of the helper class invocation.
/**
* Get the method name for a depth in call stack. <br />
* Utility function
* #param depth depth in the call stack (0 means current method, 1 means call method, ...)
* #return method name
*/
public static String getMethodName(final int depth)
{
final StackTraceElement[] ste = new Throwable().getStackTrace();
//System. out.println(ste[ste.length-depth].getClassName()+"#"+ste[ste.length-depth].getMethodName());
return ste[ste.length - depth].getMethodName();
}
For example, if you try to get the calling method line for debug purpose, you need to get past the Utility class in which you code those static methods:
(old java1.4 code, just to illustrate a potential StackTraceElement usage)
/**
* Returns the first "[class#method(line)]: " of the first class not equal to "StackTraceUtils". <br />
* From the Stack Trace.
* #return "[class#method(line)]: " (never empty, first class past StackTraceUtils)
*/
public static String getClassMethodLine()
{
return getClassMethodLine(null);
}
/**
* Returns the first "[class#method(line)]: " of the first class not equal to "StackTraceUtils" and aclass. <br />
* Allows to get past a certain class.
* #param aclass class to get pass in the stack trace. If null, only try to get past StackTraceUtils.
* #return "[class#method(line)]: " (never empty, because if aclass is not found, returns first class past StackTraceUtils)
*/
public static String getClassMethodLine(final Class aclass)
{
final StackTraceElement st = getCallingStackTraceElement(aclass);
final String amsg = "[" + st.getClassName() + "#" + st.getMethodName() + "(" + st.getLineNumber()
+")] <" + Thread.currentThread().getName() + ">: ";
return amsg;
}
/**
* Returns the first stack trace element of the first class not equal to "StackTraceUtils" or "LogUtils" and aClass. <br />
* Stored in array of the callstack. <br />
* Allows to get past a certain class.
* #param aclass class to get pass in the stack trace. If null, only try to get past StackTraceUtils.
* #return stackTraceElement (never null, because if aClass is not found, returns first class past StackTraceUtils)
* #throws AssertionFailedException if resulting statckTrace is null (RuntimeException)
*/
public static StackTraceElement getCallingStackTraceElement(final Class aclass)
{
final Throwable t = new Throwable();
final StackTraceElement[] ste = t.getStackTrace();
int index = 1;
final int limit = ste.length;
StackTraceElement st = ste[index];
String className = st.getClassName();
boolean aclassfound = false;
if(aclass == null)
{
aclassfound = true;
}
StackTraceElement resst = null;
while(index < limit)
{
if(shouldExamine(className, aclass) == true)
{
if(resst == null)
{
resst = st;
}
if(aclassfound == true)
{
final StackTraceElement ast = onClassfound(aclass, className, st);
if(ast != null)
{
resst = ast;
break;
}
}
else
{
if(aclass != null && aclass.getName().equals(className) == true)
{
aclassfound = true;
}
}
}
index = index + 1;
st = ste[index];
className = st.getClassName();
}
if(resst == null)
{
//Assert.isNotNull(resst, "stack trace should null"); //NO OTHERWISE circular dependencies
throw new AssertionFailedException(StackTraceUtils.getClassMethodLine() + " null argument:" + "stack trace should null"); //$NON-NLS-1$
}
return resst;
}
static private boolean shouldExamine(String className, Class aclass)
{
final boolean res = StackTraceUtils.class.getName().equals(className) == false && (className.endsWith("LogUtils"
) == false || (aclass !=null && aclass.getName().endsWith("LogUtils")));
return res;
}
static private StackTraceElement onClassfound(Class aclass, String className, StackTraceElement st)
{
StackTraceElement resst = null;
if(aclass != null && aclass.getName().equals(className) == false)
{
resst = st;
}
if(aclass == null)
{
resst = st;
}
return resst;
}
I've done this before. You can just create a new exception and grab the stack trace on it without throwing it, then examine the stack trace. As the other answer says though, it's extremely costly--don't do it in a tight loop.
I've done it before for a logging utility on an app where performance didn't matter much (Performance rarely matters much at all, actually--as long as you display the result to an action such as a button click quickly).
It was before you could get the stack trace, exceptions just had .printStackTrace() so I had to redirect System.out to a stream of my own creation, then (new Exception()).printStackTrace(); Redirect System.out back and parse the stream. Fun stuff.
private void parseExceptionContents(
final Exception exception,
final OutputStream out)
{
final StackTraceElement[] stackTrace = exception.getStackTrace();
int index = 0;
for (StackTraceElement element : stackTrace)
{
final String exceptionMsg =
"Exception thrown from " + element.getMethodName()
+ " in class " + element.getClassName() + " [on line number "
+ element.getLineNumber() + " of file " + element.getFileName() + "]";
try
{
out.write((headerLine + newLine).getBytes());
out.write((headerTitlePortion + index++ + newLine).getBytes() );
out.write((headerLine + newLine).getBytes());
out.write((exceptionMsg + newLine + newLine).getBytes());
out.write(
("Exception.toString: " + element.toString() + newLine).getBytes());
}
catch (IOException ioEx)
{
System.err.println(
"IOException encountered while trying to write "
+ "StackTraceElement data to provided OutputStream.\n"
+ ioEx.getMessage() );
}
}
}
Here is a part of the code that I made based in the hints showed in this topic.
Hope it helps.
(Feel free to make any suggestions to improve this code, please tell me)
The counter:
public class InstanceCount{
private static Map<Integer, CounterInstanceLog> instanceMap = new HashMap<Integer, CounterInstanceLog>();
private CounterInstanceLog counterInstanceLog;
public void count() {
counterInstanceLog= new counterInstanceLog();
if(counterInstanceLog.getIdHashCode() != 0){
try {
if (instanceMap .containsKey(counterInstanceLog.getIdHashCode())) {
counterInstanceLog= instanceMap .get(counterInstanceLog.getIdHashCode());
}
counterInstanceLog.incrementCounter();
instanceMap .put(counterInstanceLog.getIdHashCode(), counterInstanceLog);
}
(...)
}
And the object:
public class CounterInstanceLog{
private int idHashCode;
private StackTraceElement[] arrayStackTraceElements;
private int instanceCount;
private String callerClassName;
private StackTraceElement getProjectClasses(int depth) {
if(depth< 10){
getCallerClassName(sun.reflect.Reflection.getCallerClass(depth).getName());
if(getCallerClassName().startsWith("com.yourproject.model")){
setStackTraceElements(Thread.currentThread().getStackTrace());
setIdHashCode();
return arrayStackTraceElements[depth];
}
//+2 because one new item are added to the stackflow
return getProjectClasses(profundidade+2);
}else{
return null;
}
}
private void setIdHashCode() {
if(getNomeClasse() != null){
this.idHashCode = (getCallerClassName()).hashCode();
}
}
public void incrementaContador() {
this.instanceCount++;
}
//getters and setters
(...)
}
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
class DBConnection {
String createdBy = null;
DBConnection(Throwable whoCreatedMe) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
PrintWriter pw = new PrintWriter(os);
whoCreatedMe.printStackTrace(pw);
try {
createdBy = os.toString();
pw.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class ThrowableTest {
public static void main(String[] args) {
Throwable createdBy = new Throwable(
"Connection created from DBConnectionManager");
DBConnection conn = new DBConnection(createdBy);
System.out.println(conn.createdBy);
}
}
OR
public static interface ICallback<T> { T doOperation(); }
public class TestCallerOfMethod {
public static <T> T callTwo(final ICallback<T> c){
// Pass the object created at callee to the caller
// From the passed object we can get; what is the callee name like below.
System.out.println(c.getClass().getEnclosingMethod().getName());
return c.doOperation();
}
public static boolean callOne(){
ICallback callBackInstance = new ICallback(Boolean){
#Override
public Boolean doOperation()
{
return true;
}
};
return callTwo(callBackInstance);
}
public static void main(String[] args) {
callOne();
}
}
use this method:-
StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
stackTraceElement e = stacktrace[2];//maybe this number needs to be corrected
System.out.println(e.getMethodName());
Caller of method example Code is here:-
public class TestString {
public static void main(String[] args) {
TestString testString = new TestString();
testString.doit1();
testString.doit2();
testString.doit3();
testString.doit4();
}
public void doit() {
StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
StackTraceElement e = stacktrace[2];//maybe this number needs to be corrected
System.out.println(e.getMethodName());
}
public void doit1() {
doit();
}
public void doit2() {
doit();
}
public void doit3() {
doit();
}
public void doit4() {
doit();
}
}
Short answer ReflectionUtils.getCallingClass(0)
Long answer (code, Groovy)
package my
import org.codehaus.groovy.reflection.ReflectionUtils
import java.lang.reflect.Field
import java.lang.reflect.Method
trait Reflector {
static String[] fieldNames() {
List<String> names = []
Arrays.asList(naturalFields()).forEach { Field fl -> names.add(fl.name) }
return names.toArray() as String[]
}
static Field[] naturalFields() {
return finalClass().getDeclaredFields().findAll { Field fl -> !fl.synthetic }.collect()
}
static Method[] naturalMethods() {
return finalClass().getDeclaredMethods().findAll { Method md -> !md.synthetic }.collect()
}
static Class finalClass() {
return ReflectionUtils.getCallingClass(0)
}
}
class Demo implements Reflector {
int archived = 0
int demo = 100
static void playToo() {
println finalClass()
}
}
println Demo.finalClass() // class my.Demo
println Demo.naturalFields() // [private int my.Demo.archived, private int my.Demo.demo]
println Demo.fieldNames() // [archived, demo]

Java 8 Map<String, Runnable> Control Flow

I'm trying to familiarize myself with some new Java 8 functionality (ha) but I'm having some control flow mishaps.
In the following code, I have a Map<String, Runnable> so I can call methods based on their name, but I can't seem to figure out how to do two things:
How can I make these methods take parameters? I.e. what is the syntax I need in the map "put"s.
When I call these methods from the "get" method in "Dispatch, I cannot return the return value of the method (Status). I suspect this has something to do with where the method is being called, but I can't figure it out. Status is just an enum and the toList method just takes a space separated string and returns a list (this is meant to be used as a REPL).
import java.util.*;
public class Dispatcher {
private Map<String, Runnable> func;
private Status status;
private List<String> command;
Optional<List<String>> opt;
public Dispatcher() {
func = new HashMap<>();
func.put("Method1", this::Method1);
func.put("Method2", this::Method2);
func.put("Help", this::Help);
status = Status.DONE;
}
private Status Help() {
return Status.DONE;
}
private Status Method1() {
return Status.DONE;
}
private Status Method2() {
return Status.DONE;
}
/**
* Execute the given command on a new process.
* #param command the full command requested by the caller including command name and arguments.
* #return The status of the requested operation.
*/
public Status Dispatch(String command) {
opt = CommandInterpreter.toList(command);
opt.orElse(new LinkedList<String>(){{add("Help");}});
func.get(opt.get().get(0));
return Status.DONE;
}
}
Here is a skeleton how you may start do deal with commands taking zero or more arguments and returning a status code. It is just a blueprint, an example. Perhaps it helps you getting started:
public class Dispatcher {
public static final int SUCCESS = 0;
public static final int FAILURE = 1;
public static final Command HELP = (args) -> {
String command = args[0];
System.out.println("Usage of " + command + ": bla bla");
return FAILURE;
};
public static final Command RENAME = (args) -> {
File oldName = new File(args[1]);
File newName = new File(args[2]);
return oldName.renameTo(newName) ? SUCCESS : FAILURE;
};
public final Map<String, Command> commands = new HashMap<String, Command>() {{
put("help", HELP);
put("rename", RENAME);
}};
public int dispatch(String commandLine) {
String[] args = commandLine.split("\\s");
return Optional.ofNullable(commands.get(args[0]))
.orElse(HELP)
.execute(args);
}
}
interface Command {
int execute(String... args);
}
If you want the methods to take arguments, then you don't want to store it as Runnable. You might want Consumer, or another custom functional interface that accepts an argument -- if you want a return value, use Function, or create your own interface.
The Runnable interface doesn't accept any parameters or have a return type. To add a return type, you can use Supplier<Status>. To add a parameter, use Function<ParamType, Status>.

Mockito 1.9: format the expected value (like "actual formatter" in custom ArgumentMatcher)

In Mockito 1.9.5 I'd like to format the actual value when verifying the (in order) call arguments of a method.
Mockito provides a overridable describeTo method within ArcgumentMatcher<T>s that enables me to format the expected value.
When mocking JRE classes like DatagramPacket using PowerMockito's whenNew, the actual value is not formatted the way I like.
In the following example I'm only interested if the address of the DatagramPacket was called in order. If not, I'd like to see the mismatching, actual value and not the default toString() name "java.net.DatagramPacket#7546a399".
My custom matcher is able to match only the InetSocketAddress.
Example
The custom matcher:
static class IsDatagramForAddress extends ArgumentMatcher<DatagramPacket> {
final InetSocketAddress addr;
public IsDatagramForAddress(InetSocketAddress addr){
this.addr = addr;
}
public boolean matches(Object dgp) {
SocketAddress isa = ((DatagramPacket) dgp).getSocketAddress();
boolean eq = isa.equals(addr);
// System.out.println(dgp + ": " + isa + "< >" + addr + " == " + eq);
return eq;
}
#Override
public void describeTo(Description description) {
description.appendText(addr == null ? null : addr.toString());
}
}
The test:
private static DatagramPacket isDatagramForAddress(InetSocketAddress addr){
return argThat(new IsDatagramForAddress(addr));
}
...
#Test
public void testSendIsCalledWithServersInOrder() throws Exception {
InOrder order = inOrder(sock);
order.verify(sock).send(isDatagramForAddress(new InetSocketAddress("8.8.8.2", 100)));
order.verify(sock).send(isDatagramForAddress(new InetSocketAddress("8.8.8.1", 100)));
}
This is what I get:
org.mockito.exceptions.verification.VerificationInOrderFailure:
Verification in order failure
Wanted but not invoked:
datagramSocket.send(/8.8.8.1:100);
-> at xxxx.XxxxTest.testSendIsCalledWithServersInOrder(XxxxTest.java:95)
Wanted anywhere AFTER following interaction:
datagramSocket.send(
java.net.DatagramPacket#7546a399
);
-> at xxxx.XxxxTest.testSendIsCalledWithServersInOrder(XxxxTest.java:90)
at xxxx.XxxxTest.testSendIsCalledWithServersInOrder(XxxxTest.java:95)
...
This is what I expect:
org.mockito.exceptions.verification.VerificationInOrderFailure:
Verification in order failure
Wanted but not invoked:
datagramSocket.send(/8.8.8.1:100);
-> at xxxx.XxxxTest.testSendIsCalledWithServersInOrder(XxxxTest.java:95)
Wanted anywhere AFTER following interaction:
datagramSocket.send(/8.8.8.2:100);
-> at xxxx.XxxxTest.testSendIsCalledWithServersInOrder(XxxxTest.java:90)
at xxxx.XxxxTest.testSendIsCalledWithServersInOrder(XxxxTest.java:95)
...
Question boiled down
How can I format/toString() the actual value?
You could make your ArgumentMatcher store the last object that was passed to it, then include it in your describeTo method. This might look something like this.
static class IsDatagramForAddress extends ArgumentMatcher<DatagramPacket> {
final InetSocketAddress addr;
DatagramPacket lastCompared;
public IsDatagramForAddress(InetSocketAddress addr){
this.addr = addr;
}
public boolean matches(Object dgp) {
if (dgp instanceof DatagramPacket) {
lastCompared = (DatagramPacket) dgp;
SocketAddress isa = lastCompared.getSocketAddress();
return isa.equals(addr);
}
return false;
}
#Override
public void describeTo(Description description) {
description.appendText(addr == null ? null : addr.toString());
if (lastCompared != null) {
description.appendText("Last socket address was " + lastCompared.getSocketAddress());
}
}
}

Executing Java code inside a Java program

I would like to create an application which for example measures the execution time of a certain block of code. In this case it should have a structure like this:
public static long measureExecution(String code){
long start = System.nanoTime();
executeCode(code); // <----
long time = System.nanoTime() - start;
return time;
}
I'm curious about the method designated by the arrow, I need some sort of a placeholder. How should be this method implemented? Is it even possible to execute a custom Java code inside running Java application?
I was thinking that it can be done with some sort of overriding of another methods body, but I can't quite figure out how.
Thanks for your opinions!
You could pass a Runnable:
public static long measureExecution(Runnable code) {
long start = System.nanoTime();
code.run();
long time = System.nanoTime() - start;
return time;
}
At the place where you call the method, use an anonymous inner class to wrap the code you want to measure:
long time = measureExecution(new Runnable() {
#Override
public void run() {
System.out.println("Do something");
}
});
(If you were using Java 8, you could use a lambda expression instead of an anonymous inner class, which would make the code shorter and easier to read).
You can use OpenHFT/Java-Runtime-Compiler:
https://github.com/OpenHFT/Java-Runtime-Compiler
Also, you can use ToolProvider class (Compiler API), since java 1.6:
private Path compileJavaFile(Path javaFile, String className) {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
compiler.run(null, null, null, javaFile.toFile().getAbsolutePath());
return javaFile.getParent().resolve(className);
}
You could use a Dynamic Proxy to wrap your methods invocation, here an example:
First you need to create InvocationHandler class:
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target) {
this.target = target;
}
#Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("About to invoke " + method + "\n with argument " + args);
Object rv = method.invoke(target, args);
System.out.println(" Call returned " + rv);// here you could print the time instead
return rv;
}
}
Then Create a factory to get you object and Wrap it with the previous created proxy.
public class MyFactory {
public static MyInterface getMyInterface() {
MyInterface mc = new MyClass();
InvocationHandler h = new MyInvocationHandler(mc);
MyInterface mi = (MyInterface) Proxy.newProxyInstance(MyInterface.class.getClassLoader(),
new Class[] { MyInterface.class }, h);
return mi;
}
}
Hope that help you.

Categories