Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add JavaScriptFactory [SPR-1933] #6626

Closed
spring-projects-issues opened this issue Apr 19, 2006 · 13 comments
Closed

Add JavaScriptFactory [SPR-1933] #6626

spring-projects-issues opened this issue Apr 19, 2006 · 13 comments
Assignees
Labels
status: declined A suggestion or change that we don't feel we should currently apply type: enhancement A general enhancement

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Apr 19, 2006

James Tikalsky opened SPR-1933 and commented


Affects: 2.0 M4

Attachments:

Issue Links:

9 votes, 8 watchers

@spring-projects-issues
Copy link
Collaborator Author

James Tikalsky commented

Some notes:

You will need rhino.jar in your classpath for this to work. Download one here: http://www.mozilla.org/rhino/download.html
Your JavaScript will be executed so it must instantiate an object instance. For example:

---- BEGIN JS ----
function MyObject() {} // constructor function
new MyObject(); // instantiate
---- END JS ----

Your functions can return other JavaScript objects, but you'll be exposing your Java code to the Rhino's classes that represent JavaScript native types. Better to return simple values (String, Double, boolean) for now. I hope that in the future there will be a way to coerce method return types to the Java interface of your choice.

@spring-projects-issues
Copy link
Collaborator Author

James Tikalsky commented

I noticed a bug: The method requiresConfigInterface() should return true, not false.

@spring-projects-issues
Copy link
Collaborator Author

Dave Syer commented

I would vote for this if the coercion can be sorted, and if we can add a lang:javascript schema support. The other supported dynamic languages seem to handle the "coercion" (I assume by proxying), so it should't be difficult. Maybe Rick should comment...?

@spring-projects-issues
Copy link
Collaborator Author

James Tikalsky commented

I've sorted out the return type coercion. I have no idea (right now, anyway) where the schema support is. I'll package up my code and attach it to this bug in the near future.

@spring-projects-issues
Copy link
Collaborator Author

James Tikalsky commented

Please ignore the old attached .java files.

The attached spring-rhino-0-1.jar includes a fix for the return type coercion. lang:javascript support is possible if you apply the attached patch file to the LangNamespaceSupport.java and spring-lang-2.0.xsd files. Please see the attached readme.html file for more info.

@spring-projects-issues
Copy link
Collaborator Author

Andrew Fink commented

Rhino support in Spring would be "good thing".

@spring-projects-issues
Copy link
Collaborator Author

Andrew Fink commented

My bug fixed, improved, multi-thread safe, spring 3.0 compatible version "on steroids". I have also enhanced junit tests and can upload them too.

@spring-projects-issues
Copy link
Collaborator Author

Andrew Fink commented

comment fix:

org.springframework.scripting.rhino.zip

It is my bug fixed, improved, multi-thread safe, spring 3.0 compatible version "on steroids". I have also enhanced junit tests and can upload them too.

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Feb 3, 2010

Andrew Fink commented

Some examples:

#1 no spring

@Test public void testMultithread () throws InterruptedException {
AtomicInteger ai = new AtomicInteger(0);

String scriptSource =
    "new java.lang.Thread(function () {" +
        "log.println('start '+g+', me ='+ this+' @ '+java.lang.Thread.currentThread()+', '+ai); " +
        "while (g < max) { " +
          "g = g + 1;  ai.incrementAndGet(); " +
          "java.lang.Thread.yield(); " +
        "}" +//while
        "log.println('done '+g+', me ='+ this+' @ '+java.lang.Thread.currentThread());" +
      "})";
JavaScriptFactory f = new JavaScriptFactory("x", Object.class);
f.setGlobalScript("g = 0; var max = 1000; ");//thread don't see other threads g and max modifications, but you can call object methods with side effect - so exchange state 
f.setGlobals(Cast.mapOf("log", System.out, "ai", ai));//mapOf = easy map creation from google-collection


Thread[] t = new Thread[500];

long time = System.currentTimeMillis();
for (int i=0; i<t.length; i++) {
  t[i] = (Thread) f.createJavaScriptObject(scriptSource);
  t[i].start();
}
for (int i = t.length-1; i >= 0; i--) {
  t[i].join();
}

time = System.currentTimeMillis() -time;
System.out.println(time);

assertEquals(1000*500, ai.get());

}


#2 full Sprig access
<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor" />

<!-- ApplicationListener in js -->
<bean id="testSpringAppEventsListener" class="net.sf.apr.spring.JavaScriptFactory" >
<constructor-arg><value type="java.lang.String"><![CDATA[inline:
importPackage(Packages.net.sf.apr.web, Packages.org.slf4j, Packages.net.sf.apr.log);

var o = new Object();
o.onApplicationEvent = function (event) {
var log = LoggerFactory.getLogger("SpringAppEvent");
if (event instanceof ShutdownListener.WebAppEvent) {
log.info("=====");
log.info(event.toString());
log.info("servletContext: {}", LogUtil.toString(event.getServletContext()));
if (Spring === event.webApplicationContext) {log.info("Same ApplicationContext!");}
log.info("=====");
}//i
}

new Packages.org.springframework.context.ApplicationListener(o);
]]></value></constructor-arg>
<constructor-arg type="java.lang.Class" value="org.springframework.context.ApplicationListener" />
</bean>

<!-- some prototype bean handler. You can use Spring property to access all ApplicationContext -->
<bean id="clientConnection1" class="net.sf.apr.spring.JavaScriptFactory" >
<constructor-arg><value type="java.lang.String"><![CDATA[inline:
importClass(java.io.OutputStream);

function ICR () {};

ICR.prototype.setSocket = function (socket) {
var log = Packages.org.slf4j.LoggerFactory.getLogger("clientConnection1");
log.info("connected: {}", socket);
var out = socket.outputStream;
out.write(new java.lang.String("Hello, world!").bytes);
out.flush();
socket.close();

Spring.getBean("testSpringAppEventsListener").onApplicationEvent( //just for demo
new Packages.net.sf.apr.web.ShutdownListener.WebAppEvent(beanName, "/srvcntx", "srvcntx",
Spring));//1) just cool! 2) Spring prop is actually (at runtime) WebApplicationContext - so no ClasCastExc
log.info("other bean called! {} = {}", Spring.getBean("testSpringAppEventsListener"),
Spring.getBean("testSpringAppEventsListener").onApplicationEvent);
};

ICR.prototype.getSocket = function () { return null; };

ICR.prototype.run = function () {};//Runnable.run

new ICR();
]]></value></constructor-arg>
<constructor-arg value="bla.bla.IConnectionHandler"/>
</bean>

@spring-projects-issues
Copy link
Collaborator Author

Andrew Fink commented

Last version: org.springframework.scripting.rhino_100204.zip

Ok! Now it is really bug fixed and improved.

@spring-projects-issues
Copy link
Collaborator Author

Andrew Fink commented

Last version: org.springframework.scripting.rhino_100205.zip

  • bugfix (with external global script)
  • lazy js initialization

@spring-projects-issues
Copy link
Collaborator Author

Andrew Fink commented

Please add JS support to Spring.
It's much better than bsh!

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Apr 1, 2015

Juergen Hoeller commented

Superseded by #9888.

@spring-projects-issues spring-projects-issues added status: declined A suggestion or change that we don't feel we should currently apply type: enhancement A general enhancement labels Jan 10, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: declined A suggestion or change that we don't feel we should currently apply type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants