Is it possible to resume a continuation in Rhino multiple times? - java

I want to be able to capture a continuation and resume it several times, such that each such invocation would be independent of the others.
For example, in the following code, I'd want the 2 calls to context.resumeContinuation in the run method to result in the output: 1 1, rather than the current output of 1 2.
As far as I understand, the reason for the resulting output is that I always use the same scope object, which is being modified by the first continuation before being passed to the second one. So it seems that I should resume each continuation with a copy of the original scope, but type Scriptable has no clone method (or anything equivalent), and copying it using serialization/deserialization doesn't help either.
P.S. I am using Rhino version 1.7R5.
Example.java:
import org.mozilla.javascript.*;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
public class Example {
public void run() throws IOException {
Context context = Context.enter();
context.setOptimizationLevel(-2); // Use interpreter mode.
Scriptable scope = context.initStandardObjects();
scope.put("javaProxy", scope, Context.javaToJS(this, scope));
Object capturedContinuation = null;
try {
String scriptSource =
new String(Files.readAllBytes(Paths.get("example.js")));
String scriptName = "example";
int startLine = 1;
Object securityDomain = null;
Script script =
context.compileString(scriptSource, scriptName, startLine, securityDomain);
context.executeScriptWithContinuations(script, scope);
} catch (ContinuationPending continuationPending) {
capturedContinuation = continuationPending.getContinuation();
}
Object result = "";
context.resumeContinuation(capturedContinuation, scope, result);
context.resumeContinuation(capturedContinuation, scope, result);
Context.exit();
}
public void captureContinuation() {
Context context = Context.enter();
ContinuationPending continuationPending =
context.captureContinuation();
Context.exit();
throw continuationPending;
}
public void print(int i) {
System.out.print(i + " ");
}
public static void main(String[] args) throws IOException {
new Example().run();
}
}
example.js:
var i = 1;
javaProxy.captureContinuation();
javaProxy.print(i);
i = i + 1;

So I came up with a working solution:
Instead of copying the scope object, I should've copied the capturedContinuation object, so the 2 calls to resumeContinuation would be:
context.resumeContinuation(deepCopy(capturedContinuation), scope, result);
context.resumeContinuation(deepCopy(capturedContinuation), scope, result);
This question offers possible imeplementations of the deepCopy method.
A word of caution, though: instances of Rhino's NativeContinuation type (which is the dynamic type of capturedContinuation in the code above) seem to be quite large (~15KB and up when serialized to a byte array), so time/memory consumption implications should be considered when deep copying them in an application.

This is just a guess but I think this might work (Rhino 1.7.6):
NativeContinuation capturedContinuation = ...
final Object stackFrame = capturedContinuation.getImplementation();
// Invoke once...
context.resumeContinuation(capturedContinuation, scope, result);
// Put stack back where it was
capturedContinuation.initImplementation(stackFrame);
// Invoke twice...
context.resumeContinuation(capturedContinuation, scope, result);

Related

how can I write a test for void methods with junit in Java especially they do not return a value?

I have here a simple program to resolve hostname to ip address and vice versa and do not have any idea ,how can I test these two void methods with junit , as long they don't return any values.
I need help with junit test , because my void methods don't return any thing.
/*
* inside this interface we have two function,that
* resolve ip to host-addr and vice versa
*/
public interface DnsFunctions {
public void resolveHostToIp();
public void resolveIpToHost();
}
and here ist the main code for the Dns resolver where the void methods are invoked inside the switch case :
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class DnsResolver implements DnsFunctions {
static BufferedReader br;
static DnsFunctions df = new DnsResolver();
static boolean status = true;
public static void main(String[] args) throws NumberFormatException, IOException {
StringBuilder sb = new StringBuilder();
sb.append("Welcome to DNS-resolver page :");
sb.append("\n*select (1) to resolve Hostname to IP-Address");
sb.append("\n*select (2) to get the Host name from inputed IP-Address");
sb.append("\n*select (3) for EXIT");
System.out.println(sb);
/*
* depending on the inputted value from user /1-2 or 3/ the suitable function
* will be called
*/
while (status) {
br = new BufferedReader(new InputStreamReader(System.in));
int inputedValue = Integer.parseInt(br.readLine());
switch (inputedValue) {
case 1:
df.resolveHostToIp();
status = true;
break;
case 2:
df.resolveIpToHost();
status = true;
break;
case 3:
status = false;
System.out.println("GoodBye :)");
break;
}
}
}
#Override
/*
*
* #parameter value
*/
public void resolveHostToIp() {
try {
System.out.println("\n Enter Hostname:");
String hostName = br.readLine();
InetAddress address = InetAddress.getByName(hostName);
System.out.println("Hostname :" + address.getHostName());
System.out.println("IP:" + address.getHostAddress());
} catch (Exception e) {
System.out.println("ERROR :(" + e.getMessage());
}
}
#Override
/*
* #parameter value
*/
public void resolveIpToHost() {
try {
System.out.println("\n Enter IP address");
String ip_add = br.readLine();
InetAddress ia = InetAddress.getByName(ip_add);
System.out.println("IP: " + ip_add);
System.out.println("Host Name: " + ia.getHostName());
} catch (IOException e) {
System.out.println("ERROR :(" + e.getMessage());
}
}
}
The problem is that the only observable effect produced by these methods is that they write to System.out. Nothing more. And the interface doesn't indicate that in any way.
One option to test the implementation would be to redirect and observe System.out. If, however, there's ever a different implementation which doesn't write to System.out then that would fail the test. It'll work if you're reluctant to change the code, but has its downsides as well.
If on the other hand you can change the code, then you can make the methods more testable by having them return their values instead of printing their values. Then in the main() method you would print the returned values.
The benefit here becomes cleaner testability by separating the concern of producing the value from the concern of outputting the value. They're two different things and should be handled separately, even if both are small and simple.
From a purist unit testing perspective, you'd likely also want to encapsulate the dependency on the static methods in InetAddress, likely by wrapping it in a mockable object and injecting a mock for the test.
It approaches an interesting problem though, because once both of these dependencies are removed then the methods effectively don't do anything and the value of testing them in the first place quickly approaches zero. They'd just be a pass-through to the mock that's being injected, nothing more.
For the immediate purpose, I'd recommend removing the System.out dependency and keeping that solely in the main() method, having the methods return their values. And then re-classifying your unit tests as "integration tests" with a known dependency on InetAddress.
This is (almost) untestable with jUnit. And pretty useless also, when we look into the implemention.
The main blocker: It's a unit test so we don't want to invoke the real getByName method on InetAdress. We'd have to mock it. But it's a static method and jUnit can't mock that.
The challenges: we'd have to replace System.out and System.in by methods where we can pass our test data (into the System.in) and assert the output (from the mocked System.out).
The challenges are solvable, the static method problem requires rewriting your code.
You can mock InetAddress.getByName(ip_add); call and then add a check like - assertEquals("StringThatShouldComeUpOnConsole", outContent.toString());

How can a volatile field be unique to each thread when the constructor is only called once?

I was doing some tests with Flink framework and stumbled upon a behavior that seemed very strange at first.
In my code, I used a custom PngOutputFormat class that had a
private volatile AtomicInteger numFile;
field.
Now, when the whole program was run, the PngOutputFormat constructor was called only once.
Yet a method where the field was used as follows
int numImage = numFile.incrementAndGet();
later output the same numImage value 12 (the amount of parallel tasks) or less times.
I have to declare the numFile field static on top of that to ensure that a different numImage value is output each time.
But from my prior understanding, volatile (and atomic) was enough to share the variable between threads and synchronize the access.
I've been thinking about it and looking for answers for a while and have since come up with one seemingly reasonable explanation:
A PngOutputFormat is instantiated in a non-parallel environment.
Mutliple threads are created. Each copies the PngOutputFormat object through deserialization, therefore not invoking the constructor again.
Each object then has a unique set of class fields and threads work completely independently.
Only static identifier ensures that threads use a reference to the same field object.
Am I correct in my assertion? Otherwise how does it work? And is the aforedescribed scenario even possible?
(I've tried using System.identityHashCode(obj) and apparently passing this (PngOutputFormat) indeed returns different object IDs. Passing the static numFile returns the same one and passing the non-static numFile returns 12 different IDs (yet when it throws an exception, the close method is called 24 times - twice as much ... maybe the objects are recreated in an attempt to resolve the exception?). But I'll still ask this answer to make sure, hope you don't mind. Here's the class code for anyone interested :
import org.apache.flink.api.common.io.RichOutputFormat;
import org.apache.flink.configuration.Configuration;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
/**
* A more generic output format for outputing each element into a separate PNG file.
* The type of elements is generic even though we'll only use it on byte[] images.
* #param <T>
*/
public class PngOutputFormat<T> extends RichOutputFormat<T> {
private final String directoryPath;
private final String suffix;
private static volatile AtomicInteger numFile;
private final int numCols;
private final int numRows;
private BufferedImage image;
private WritableRaster raster;
public PngOutputFormat(String directoryPath, String suffix, int numCols, int numRows) {
this.directoryPath = directoryPath;
this.suffix = suffix;
this.numCols = numCols;
this.numRows = numRows;
numFile = new AtomicInteger();
}
#Override
public void configure(Configuration parameters) {
// for now, we pass the parameters through the constructor
}
#Override
public void open(int taskNumber, int numTasks) throws IOException {
image = new BufferedImage(numCols, numRows, BufferedImage.TYPE_BYTE_GRAY);
raster = image.getRaster();
new File(directoryPath).mkdirs(); // make any directories that don't exist
}
#Override
public void writeRecord(T record) throws IOException {
int numImage = numFile.incrementAndGet();
String filePath = directoryPath + numImage + '_' + suffix + ".png";
raster.setDataElements(0, 0, numCols, numRows, record);
image.setData(raster);
File outputFile = new File(filePath);
ImageIO.write(image, "png", outputFile);
System.out.println("Image nr. " + numImage + " written!");
}
#Override
public void close() throws IOException {
// The ImageIO closes the stream after each write, so we don't need to close anything.
}
}
It only happens when running Filter programs like this one, but I guess that's because Flink decides to process only these in parallel and others sequentially.)
Given that you've copied the original object by serializing/deserializing it, you now have multiple volatile numFile fields (one per instance of the class). If you want to use a global incrementing counter, which is reset when the program restarts, a private static final AtomicLong would be the idiomatic way to do it.
Note that making an Atomic* "variable" volatile only means that the reference to that object is made volatile, which in your case seems like it would have no effect.
In general, volatile should only be used for optimising memory layout if an Atomic* instance is too expensive, IMHO.

How to dynamically create a Groovy Closure from a String in Java

I would like to know how to create a Closure object at run-time from within a Java application, where the content of the Closure is not known ahead of time. I have found a solution but I doubt that it is optimal.
Background: I have written some Groovy code that parses a Domain Specific Language. The parsing code is statically compiled and included in a Java application. In the parser implementation I have classes acting as delegates for specific sections of the DSL. These classes are invoked using the following pattern:
class DslDelegate {
private Configuration configuration
def section(#DelegatesTo(SectionDelegate) Closure cl) {
cl.delegate = new SectionDelegate(configuration)
cl.resolveStrategy = Closure.DELEGATE_FIRST
cl()
}
}
I wish to call such a method directly from Java code. I am able to create a new DslDelegate object and then invoke the section() method. However I need to create and pass an argument that is an instance of Closure. I want the content to be initialised from a String object.
My Solution: The following Java code (utility) is working but I am asking for improvements. Surely this can be done in a cleaner or more efficient manner?
/**
* Build a Groovy Closure dynamically
*
* #param strings
* an array of strings for the text of the Closure
* #return a Groovy Closure comprising the specified text from {#code strings}
* #throws IOException
*/
public Closure<?> buildClosure(String... strings) throws IOException {
Closure<?> closure = null;
// Create a method returning a closure
StringBuilder sb = new StringBuilder("def closure() { { script -> ");
sb.append(String.join("\n", strings));
sb.append(" } }");
// Create an anonymous class for the method
GroovyClassLoader loader = new GroovyClassLoader();
Class<?> groovyClass = loader.parseClass(sb.toString());
try {
// Create an instance of the class
GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance();
// Invoke the object's method and thus obtain the closure
closure = (Closure<?>) groovyObject.invokeMethod("closure", null);
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
} finally {
loader.close();
}
return closure;
}
You can use GroovyShell to create a Closure from strings:
public Closure<?> buildClosure(String... strings) {
String scriptText = "{ script -> " + String.join("\n", strings) + " }";
return (Closure<?>) new GroovyShell().evaluate(scriptText);
}
Thanks to #hzpz I've soved the similar task, but I'd made it more beautiful and easy-to-use. In my case the closure might accept any arguments, so I put arguments list to closures code. Lets say the closure dynamically created in the String and looks like this:
script1 = 'out,a,b,c-> out.println "a=${a}; b=${b}; c=${c}"; return a+b+c;'
Now, create new method in the String class
String.metaClass.toClosure = {
return (Closure) new GroovyShell().evaluate("{${delegate}}")
}
Now I can call a closure from String or file or from anything else.
println script1.toClosure()(out,1,2,3)
or
println (new File('/folder/script1.groovy')).getText('UTF-8').toClosure()(out,1,2,3)

How to call a Java Class with parameters that is in another Jar, multiple times in Parallel

I have a project in RAD. Package is inputFileEdit, and the java class I need is InputFileTest.java.
package inputFileEdit;
public class InputFileTest {
public static void main(String[] args) {
String var1 = args[0];
String var2 = args[1].toLowerCase();
// do stuff with args
}
}
I want to create a new package / java program that can call or instantiate the class InputFileTest above, with arguments, multiple times in parallel. I'm basically going to be bringing back a String list, looping through that list to create parallel threads, each row on the list calling InputFileTest.
Question 1) What's the best way to call InputFileTest? I'm using RAD and I created a new Project, a package called CallerPackage, and a Caller.java inside that package? I also including a "Jar" of the whole InputFileEdit project under /lib via Java Build Path -> Libraries -> Add External Jars. I don't know how to call the class with parameters (I tried something like InputFileEdit ifeObj = new InputFileEdit("parm 1", "parm 2"); or InputFileEdit ifeObj = new InputFileEdit("parm 1 parm 2");) but neither worked so then I tried to just call the jar like Process p = Runtime.getRuntime().exec("java -jar /lib/InputFileEdit.jar parm1 parm2"); or since I want the actual Class InputFileTest, Process p = Runtime.getRuntime().exec(new String[]{"java","-cp","/lib/InputFileEdit.jar", "InputFileTest", "parm1","parm1"});:
package CallerPackage;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
//import inputFileEdit.*;
public class Caller {
static int i = 0;
public static void main(String args[]) throws IOException, InterruptedException {
try {
System.out.println("Calling jar");
Process p = Runtime.getRuntime().exec("java -jar /lib/InputFileEdit.jar parm1 parm2");
BufferedInputStream errStrm = new BufferedInputStream(p.getErrorStream());
// get the error stream of the process and print it
for (int i = 0; i < errStrm.available(); i++) {
System.out.println("" + errStrm.read());
}
System.out.println("Called jar");
p.destroy();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}
but this doesn't seem to work either or print out anything helpful. Any ideas of the best way to go about this? I'm only trying to get 1 call to work for now before I loop through my list and call them in parallel. Eventually it'll be calling the jar/class looping through a string arraylist.
you should be able to call the main method in InputFileTest the same way you would call any other static method: InputFileTest.main(args);
However, generally directly calling main is frowned upon. If you are able, I would advise you to take the code in InputFileTest's main, and put it into another, more descriptively named method, something like processFiles.

How to improve logging mechanism with Java8s lambdas

How is it possible, to improve your logging mechanism, by not having the overhead of string concatenations?
Consider the following example:
import java.util.logging.Level;
import java.util.logging.Logger;
public class LoggerTest {
public static void main(String[] args) {
// get logger
Logger log = Logger.getLogger(LoggerTest.class.getName());
// set log level to INFO (so fine will not be logged)
log.setLevel(Level.INFO);
// this line won't log anything, but will evaluate the getValue method
log.fine("Trace value: " + getValue());
}
// example method to get a value with a lot of string concatenation
private static String getValue() {
String val = "";
for (int i = 0; i < 1000; i++) {
val += "foo";
}
return val;
}
}
The log method log.fine(...) will not log anything, because the log level is set to INFO. The problem is, that the method getValue will be evaluated anyway.
And this is a big performance issue in big applications with a lot of debug statements.
So, how to solve this problem?
Since Java8 it is possible to use the new introduced lambda expressions for this scenario.
Here is a modified example of the logging:
LoggerTest.class
import java.util.logging.Level;
import java.util.logging.Logger;
public class LoggerTest {
public static void main(String[] args) {
// get own lambda logger
LambdaLogger log = new LambdaLogger(LoggerTest.class.getName());
// set log level to INFO (so fine will not be logged)
log.setLevel(Level.INFO);
// this line won't log anything, and will also not evaluate the getValue method!
log.fine(()-> "Trace value: " + getValue()); // changed to lambda expression
}
// example method to get a value with a lot of string concatenation
private static String getValue() {
String val = "";
for (int i = 0; i < 1000; i++) {
val += "foo";
}
return val;
}
}
LambdaLogger.class
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;
public class LambdaLogger extends Logger {
public LambdaLogger(String name) {
super(name, null);
}
public void fine(Callable<String> message) {
// log only, if it's loggable
if (isLoggable(Level.FINE)) {
try {
// evaluate here the callable method
super.fine(message.call());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
With this modification you can improve the performance of your applications a lot, if you have many log statements, which are only for debugging purposes.
Of course you can use any Logger you want. This is only an example of the java.util.Logger.
#bobbel has explained how to do it.
I'd like to add that while this represents a performance improvement over your original code, the classic way of dealing with this is still faster:
if (log.isLoggable(Level.FINE)) {
log.fine("Trace value: " + getValue());
}
and only marginally more verbose / wordy.
The reason it is faster is that the lambda version has the additional runtime overheads of creating the callable instance (capture cost), and an extra level of method calls.
And finally, there is the issue of creating the LambdaLogger instances. #bobbel's code shows this being done using a constructor, but in reality java.util.logging.Logger objects need to be created by a factory method to avoid proliferation of objects. That implies a bunch of extra infrastructure (and code changes) to get this to work with a custom subclass of Logger.
Apparently Log4j 2.4 includes support for lambda expressions which are exactly useful for your case (and which other answers have replicated manually):
From https://garygregory.wordpress.com/2015/09/16/a-gentle-introduction-to-the-log4j-api-and-lambda-basics/
// Uses Java 8 lambdas to build arguments on demand
logger.debug("I am logging that {} happened.", () -> compute());
Just create wrapper methods for your current logger as:
public static void info(Logger logger, Supplier<String> message) {
if (logger.isLoggable(Level.INFO))
logger.info(message.get());
}
and use it:
info(log, () -> "x: " + x + ", y: " + y);
Reference: JAVA SE 8 for the Really Impatient eBook, pages 48-49.
use a format String, and an array of Supplier<String>. this way no toString methods are called unless the the log record is actually publishable. this way you dont have to bother with ugly if statements about logging in application code.

Categories

Resources