4

I'm working on a project that makes really heavy use of the javax.script.* packages. I have a situation where I would like to create JavaScript objects that extend an Abstract Java Class, much like you can use Invocable.getInterface to make JavaScript objects that implement Java interfaces. Is this possible? And, if so, how do you do it?

2 Answers 2

2

Yes, you can; previous poster is wrong. See the documentation for JavaAdapter.

Sign up to request clarification or add additional context in comments.

4 Comments

Unfortunately, I'm using the built-in stuff in the javax.script namespace which doesn't expose all of the underlying Rhino objects. My question was pretty specific to that situation, but this is still a somewhat useful answer.
Actually, this is exposed in the javascript side and should still work with javax.script
Important note: the "documentation" for JavaAdapter is a joke -- there's a paragraph on the linked page, and a few sites around the net have generated JavaDoc with literally no commentary at all. :( Also, as Michael points out, you can do this -- in your Javascript code, you have to pass out new JavaAdapter(MyJavaClass, {myOverloadedFunc: function(a,b){return a+b;}), which you can cast to a MyJavaClass using Context.jsToJava (that one actually has docs).
The JavaAdapter object provided by default in JRE6+'s javax.script package won't let you implement abstract classes in javascript. Only interfaces can be implemented using JavaAdapter. See Java Scripting. Not sure I agree with this statement from Oracle... > The uses of JavaAdapter to extend a Java class or to implement > multiple interfaces are very rare. ... extending Abstract classes is rare?
0

Unless you want to go the route of generating bytecode at runtime (using BCEL as below) then no. You can do it with interfaces using proxy classes but there is no equivalent for abstract classes.

If you really want to try BCEL, your best strategy is to do this:

  1. Write a method that uses BCEL to generate a byte[] of bytecode for a new class that extends the abstract class and delegates every abstract method to JavaScript.
  2. Define a naming convention that relates abstract classes to the wrapper, e.g. foo.MyAbstractClass corresponds to foo.MyAbstractClassDynamicLangWrapper.
  3. Roll a ClassLoader that implements findClass to recognize that naming convention and to generate the class bytes and calls defineClass
  4. Make sure your scripting language uses your custom classloader to resolve class names in scripts. I think in Rhino you use setApplicationClassLoader but I'm not sure.

4 Comments

That sounds nasty. I think I'll come up with another solution, if that's the case.
@Mike Samuel What about java to typescript. i mean vise versa. I am working on a project which is implementing some java native functions. What is the best way to do this ?
@9me, are you running javascript compiled from typescript in Rhino?
No. I have a package written in java, and using some inner java classes ie java.util.stream. And now I am re-writing that package in typescript. I am able to implement my package logic, but what about java.util.stream I can not implement now java class stream class at all. So my question was in my case what is the best way to do that ? I am trying to implementing few functions, but that is not enough. Thank you

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.