Similar to dynamic SQL, wherein a String is executed as an SQL at runtime, can we have Java code run dynamically? Like I return a String which is a Java code and then I execute at runtime. Is this possible?
For real Java code, this is possible using the JavaCompiler interface. However, it's very inconvenient to use since it's just an interface to a real Java compiler that expects to compile entire class definitions found in files.
The easiest way to execute code supplied at runtime would be to use the Rhino JavaScript engine.
Both of these options have been only in Java 6, though I believe the scripting interface existed before, so you could use Rhino in an earlier JRE if you download and add it to the classpath.
Javassist
You would need to use a bytecode manipulation library such as Javassist (Wikipedia), in order to run an arbitrary string that is provided at runtime. Javassist allows you to create a CtClass based on a string representing source code; and can then turn this into compiled Class object via a particular classloader, so that the class is then available to your application. Other libraries would need to do something similar to these two steps in order to achieve the same thing.
So it is possible, but it's very heavyweight and is likely to make your application very hard to reason about. If at all possible, consider designing a very flexible class statically, and having it accept parameters that control its behaviour.
If you want to do more than invoke an existing method dynamically, you may need to compile your String into bytecode. An easy way to do this is to include the Eclipse/JDT compiler jar in your classpath, and then you can use that to compile your String into a Class, which can then be loaded.
This type of dynamic code generation and execution is used to convert JSP files into Servlets and is used in other packages such as JasperReports to turn a report specification into a Class that is then invoked.
Remember that just as with SQL you must be careful to prevent code injection security problems if any of the String contains user-specified data.
You also may want to look at Java 6 scripting support:
http://download.oracle.com/javase/6/docs/technotes/guides/scripting/programmer_guide/index.htm
Here is a version of hello world that creates array of strings and prints a first one:
import javax.script.*;
public class EvalScript {
public static void main(String[] args) throws Exception {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
engine.eval("var a=java.lang.reflect.Array.newInstance(java.lang.String, 1);a[0]='Hello World';print(a[0])");
}
}
Yes it is possible. Look at the Java Compiler API. Have a look here:
http://download.oracle.com/javase/6/docs/api/javax/tools/JavaCompiler.html
Have a look at Beanshell. It provides an interpreter with java like syntax.
Related
I am trying to let users of my program rename classes and methods in the class. The new names can be read in and configured at run time and they will call these classes and methods in a scripting language using Java Script Engine. I need a way to bind their new names to the real names of the classes and methods. I have been looking at Reflection but I do not think this can provide me with the capability I need, or is this even possible?
Ex:
public class RealName {
public void printHello() {
System.out.println("Hello");
}
}
Then in maybe Paython say
obj = new NewName()
obj.hello()
Tell me if this is impossible please!
You can not change the method names, but you can bind an instance of an object to a given name and inject that into the context of the scripting language.
This would only work for that instance of the class, not for instantiating new instances.
If you really want this you may be able to generate sub classes with the new name and method names in the target scripting language and inject them into to the context to get the effect you are looking for.
Having said all that I can't really come up with a good reason to do any of this.
To answer my question from what I've found no you cannot use reflection to bind a class to a new name. In fact I found no easy way to do dynamic renaming.
What I did to overcome this was to write code from a string to a file, save that file with extension .java, compile that file, then use it with reflection or better yet use it inside a script using the Java ScriptEngine API (that way you can avoid the ugly reflection code and actually have everything dynamic and on the fly).
Here's a starting point for creating the file,
Dynamic in-memory compilation
And here's something for scripting Java,
Scripting for Java
I would like to know if it is possible to use ctags to extract class usage from within Java methods. So far, I was able to only use it to get a listing of methods and instance variables but not which classes are utilized within methods.
E.g.
...
public void doSomething(MyClass myClassInst) {
int someVar = myClassInst.getSomeVar();
System.out.println("Some var is " + someVar);
}
...
Right now all I get is a recognition of the method declaration. But I would like to extract that doSomething is also utilizing the classes MyClass and System but not just to parse the text but also know the full class address including the package (java.lang.System and com.mypackage.MyClass).
In order to be able to extract this kind of metadata, ctags would need to have access to the compiler's abstract syntax tree and I am not sure if it does that or it simply does text parsing of the source code.
Is there a way to accomplish what I am trying to do using ctags or does it eclipse the scope of its functionality?
You can use asm or BCEL to achieve this.
Are there any tool that will compile a java .properties file to a class which I can use in Java EE (tomcat) application? Similar to android where the eclipse plugin produces a static R.strings class.
I found this article:
http://www.techhui.com/profiles/blogs/localization-in-gwt-using
But it is dependant on GWT. Any help appreciated.
I have never heard about such tool. GWT has a great deferred-binding based technique but it is not the thing you are looking for. However I think it is possible to implement a basic code generator for such tasks.
But the answer to your question is: as far as I know there isn't.
To internationalize applications I implemented a Message Compiler, which creates the resource bundle files and constant definitions as Java enums or static final strings for the keys from one single source file. So the constants can be used in the Java source code, which is a much safer way than to use plain strings. In this case you also get a compile time error, when you use a key constant, that doesn't exist. The message compiler cannot only be used for Java. It creates also resource files and constants for Objective-C or Swift and can be extended for other programming environments.
What about ResourceBundle?
// refers to "src/config.properties"
ResourceBundle config = ResourceBundle.getBundle("config");
String property1 = config.getString("property1");
I think one could write a very simple grammar for properties files using ANTLR in a custom a maven plugin (or Ant task) that just generates the Java source before the compilation step.
How about storing your properties in a JSON file. The JSON object stored in the file should map to a Java class, use Jackson mapper to deserialize. With Jackson you can enforce that all fields must be non-null on deserialize.
You can also use GSON and write a custom deserializer that performs checks as strict as you want them. Example - you can enforce not null along with not empty for strings.
Compiler Assisted Localization (CAL10N) is not exactly what you asked, but may be of help.
Although it does not generate Java classes from .properties, using enums as message keys is still better than strings, as you get some help from the compiler.
Declare a enum, bind it to .properties with annotation and use enum values in message lookups. I have not tried it yet, though. See manual.
I have a question which I am not sure can be answered.
I have a php script on a server that automatically generates a java method based on table contents in a MySQL Database. The script creates a .java file in which this method is saved.
I then download this method and copy and paste the method into my main java class. I think this is an unnecessary step. Is there a way to include the method in the java class rather than copying and pasting.
I am looking to write a reference to the method.java file at the point in the java class where the method should be copied and pasted.
Something like:
public class ShowAlert {
public void showAlert(String toast) throws IOException {
System.out.println("alert = "+externalMethod());
}
include(externalMethod.java);
}
and then externalMethod.java has
public String externalMethod(){
return "hello world";
}
I am not sure if this is possible but it would be great if it was.
There is no "include file" facility in Java. I suggest that you generate this instead:
public class GeneratedClass {
public static String externalMethod(){
return "hello world";
}
}
and call it like this:
GeneratedClass.externalMethod();
That way, the handwritten file and the generated file can be completely separate.
You should really consider to use something like Java ScriptEngine (described in JSR 223). Examples can be found here.
There are also LUA integrations for Java.
You would ideally keep generated code and manually written code in separate files. In that way you wont have to do what you are doing. Use Aasmund's suggestion. That's the right way to go. You might have to restructure your code to allow this, but better now than later.
I would ask you to go the extra mile and use interfaces. Your generated code should implement an interface and your manual code should reference everything using the interface alone. You could have a Factory that returns the instance.
This will allow you to increase your decoupling of manual code and the generated code. I would think that would you are doing is using the DAO (data access object) pattern to a certain extent. The DAO pattern works best, if you keep the generated code separate and access it using interfaces. Using interfaces will allow you to change the implementation of the DAO to something else at runtime - such as to run unit tests.
You could use a PHP template engine like Smarty to create your complete java class. Your main class will be your template with a placeholder for the generated method.
Similar to dynamic SQL, wherein a String is executed as an SQL at runtime, can we have Java code run dynamically? Like I return a String which is a Java code and then I execute at runtime. Is this possible?
For real Java code, this is possible using the JavaCompiler interface. However, it's very inconvenient to use since it's just an interface to a real Java compiler that expects to compile entire class definitions found in files.
The easiest way to execute code supplied at runtime would be to use the Rhino JavaScript engine.
Both of these options have been only in Java 6, though I believe the scripting interface existed before, so you could use Rhino in an earlier JRE if you download and add it to the classpath.
Javassist
You would need to use a bytecode manipulation library such as Javassist (Wikipedia), in order to run an arbitrary string that is provided at runtime. Javassist allows you to create a CtClass based on a string representing source code; and can then turn this into compiled Class object via a particular classloader, so that the class is then available to your application. Other libraries would need to do something similar to these two steps in order to achieve the same thing.
So it is possible, but it's very heavyweight and is likely to make your application very hard to reason about. If at all possible, consider designing a very flexible class statically, and having it accept parameters that control its behaviour.
If you want to do more than invoke an existing method dynamically, you may need to compile your String into bytecode. An easy way to do this is to include the Eclipse/JDT compiler jar in your classpath, and then you can use that to compile your String into a Class, which can then be loaded.
This type of dynamic code generation and execution is used to convert JSP files into Servlets and is used in other packages such as JasperReports to turn a report specification into a Class that is then invoked.
Remember that just as with SQL you must be careful to prevent code injection security problems if any of the String contains user-specified data.
You also may want to look at Java 6 scripting support:
http://download.oracle.com/javase/6/docs/technotes/guides/scripting/programmer_guide/index.htm
Here is a version of hello world that creates array of strings and prints a first one:
import javax.script.*;
public class EvalScript {
public static void main(String[] args) throws Exception {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
engine.eval("var a=java.lang.reflect.Array.newInstance(java.lang.String, 1);a[0]='Hello World';print(a[0])");
}
}
Yes it is possible. Look at the Java Compiler API. Have a look here:
http://download.oracle.com/javase/6/docs/api/javax/tools/JavaCompiler.html
Have a look at Beanshell. It provides an interpreter with java like syntax.