SPR-6268: Add proxy-target-class to <lang:groovy/>

This commit is contained in:
David Syer
2011-06-17 12:14:01 +00:00
parent 5bfeb34b89
commit 64fd0b081d
11 changed files with 305 additions and 120 deletions

View File

@@ -21,6 +21,7 @@ import java.lang.reflect.Field;
import junit.framework.TestCase;
import org.springframework.aop.framework.Advised;
import org.springframework.aop.support.AopUtils;
import org.springframework.aop.target.dynamic.AbstractRefreshableTargetSource;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
@@ -32,7 +33,10 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ScriptingDefaultsTests extends TestCase {
private static final String CONFIG =
"org/springframework/scripting/config/scriptingDefaultsTests.xml";
"org/springframework/scripting/config/scriptingDefaultsTests.xml";
private static final String PROXY_CONFIG =
"org/springframework/scripting/config/scriptingDefaultsProxyTargetClassTests.xml";
public void testDefaultRefreshCheckDelay() throws Exception {
@@ -73,4 +77,10 @@ public class ScriptingDefaultsTests extends TestCase {
assertEquals(otherBean, testBean.getOtherBean());
}
public void testDefaultProxyTargetClass() {
ApplicationContext context = new ClassPathXmlApplicationContext(PROXY_CONFIG);
Object testBean = context.getBean("testBean");
assertTrue(AopUtils.isCglibProxy(testBean));
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.scripting.groovy;
import org.springframework.scripting.ConfigurableMessenger;
/**
* @author Dave Syer
*
*/
public class ConcreteMessenger implements ConfigurableMessenger {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}

View File

@@ -16,7 +16,13 @@
package org.springframework.scripting.groovy;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import groovy.lang.DelegatingMetaClass;
import groovy.lang.GroovyObject;
@@ -178,8 +184,7 @@ public class GroovyScriptFactoryTests {
try {
new ClassPathXmlApplicationContext("org/springframework/scripting/groovy/groovyBrokenContext.xml");
fail("Should throw exception for broken script file");
}
catch (NestedRuntimeException ex) {
} catch (NestedRuntimeException ex) {
assertTrue("Wrong root cause: " + ex, ex.contains(ScriptCompilationException.class));
}
}
@@ -194,12 +199,12 @@ public class GroovyScriptFactoryTests {
script.suggestedClassName();
mock.setReturnValue("someName");
mock.replay();
GroovyScriptFactory factory = new GroovyScriptFactory(ScriptFactoryPostProcessor.INLINE_SCRIPT_PREFIX + badScript);
GroovyScriptFactory factory = new GroovyScriptFactory(ScriptFactoryPostProcessor.INLINE_SCRIPT_PREFIX
+ badScript);
try {
factory.getScriptedObject(script, new Class[]{});
factory.getScriptedObject(script, new Class[] {});
fail("Must have thrown a ScriptCompilationException (no public no-arg ctor in scripted class).");
}
catch (ScriptCompilationException expected) {
} catch (ScriptCompilationException expected) {
assertTrue(expected.contains(InstantiationException.class));
}
mock.verify();
@@ -215,12 +220,12 @@ public class GroovyScriptFactoryTests {
script.suggestedClassName();
mock.setReturnValue("someName");
mock.replay();
GroovyScriptFactory factory = new GroovyScriptFactory(ScriptFactoryPostProcessor.INLINE_SCRIPT_PREFIX + badScript);
GroovyScriptFactory factory = new GroovyScriptFactory(ScriptFactoryPostProcessor.INLINE_SCRIPT_PREFIX
+ badScript);
try {
factory.getScriptedObject(script, new Class[]{});
factory.getScriptedObject(script, new Class[] {});
fail("Must have thrown a ScriptCompilationException (no oublic no-arg ctor in scripted class).");
}
catch (ScriptCompilationException expected) {
} catch (ScriptCompilationException expected) {
assertTrue(expected.contains(IllegalAccessException.class));
}
mock.verify();
@@ -254,8 +259,7 @@ public class GroovyScriptFactoryTests {
try {
new GroovyScriptFactory(null);
fail("Must have thrown exception by this point.");
}
catch (IllegalArgumentException expected) {
} catch (IllegalArgumentException expected) {
}
}
@@ -264,8 +268,7 @@ public class GroovyScriptFactoryTests {
try {
new GroovyScriptFactory("");
fail("Must have thrown exception by this point.");
}
catch (IllegalArgumentException expected) {
} catch (IllegalArgumentException expected) {
}
}
@@ -274,8 +277,7 @@ public class GroovyScriptFactoryTests {
try {
new GroovyScriptFactory("\n ");
fail("Must have thrown exception by this point.");
}
catch (IllegalArgumentException expected) {
} catch (IllegalArgumentException expected) {
}
}
@@ -284,8 +286,7 @@ public class GroovyScriptFactoryTests {
try {
new ClassPathXmlApplicationContext("lwspBadGroovyContext.xml", getClass());
fail("Must have thrown a BeanCreationException ('inline:' prefix was preceded by whitespace");
}
catch (BeanCreationException expected) {
} catch (BeanCreationException expected) {
assertTrue(expected.contains(FileNotFoundException.class));
}
}
@@ -312,12 +313,12 @@ public class GroovyScriptFactoryTests {
try {
factory.getScriptedObject(null, null);
fail("Must have thrown a NullPointerException as per contract ('null' ScriptSource supplied");
}
catch (NullPointerException expected) {
} catch (NullPointerException expected) {
}
}
@Ignore // see http://build.springframework.org/browse/SPR-TRUNKQUICK-908
@Ignore
// see http://build.springframework.org/browse/SPR-TRUNKQUICK-908
@Test
public void testResourceScriptFromTag() throws Exception {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("groovy-with-xsd.xml", getClass());
@@ -375,6 +376,32 @@ public class GroovyScriptFactoryTests {
assertTrue(ctx.getBeansOfType(Messenger.class).values().contains(messenger));
}
@Test
// Test for SPR-6268
public void testRefreshableFromTagProxyTargetClass() throws Exception {
ApplicationContext ctx = new ClassPathXmlApplicationContext("groovy-with-xsd-proxy-target-class.xml",
getClass());
assertTrue(Arrays.asList(ctx.getBeanNamesForType(Messenger.class)).contains("refreshableMessenger"));
Messenger messenger = (Messenger) ctx.getBean("refreshableMessenger");
assertTrue(AopUtils.isAopProxy(messenger));
assertTrue(messenger instanceof Refreshable);
assertEquals("Hello World!", messenger.getMessage());
assertTrue(ctx.getBeansOfType(ConcreteMessenger.class).values().contains(messenger));
}
@Test
// Test for SPR-6268
public void testProxyTargetClassNotAllowedIfNotGroovy() throws Exception {
try {
new ClassPathXmlApplicationContext("jruby-with-xsd-proxy-target-class.xml", getClass());
} catch (BeanCreationException e) {
assertTrue(e.getMessage().contains("Cannot use proxyTargetClass=true"));
}
}
@Test
public void testAnonymousScriptDetected() throws Exception {
ApplicationContext ctx = new ClassPathXmlApplicationContext("groovy-with-xsd.xml", getClass());
@@ -404,8 +431,7 @@ public class GroovyScriptFactoryTests {
try {
ctx.getBean("bean3");
fail("Should have thrown BeanCreationException");
}
catch (BeanCreationException ex) {
} catch (BeanCreationException ex) {
// expected
assertTrue(ex.contains(UnsatisfiedDependencyException.class));
}
@@ -424,8 +450,7 @@ public class GroovyScriptFactoryTests {
private void testMetaClass(final String xmlFile) {
// expect the exception we threw in the custom metaclass to show it got invoked
try {
ApplicationContext ctx =
new ClassPathXmlApplicationContext(xmlFile);
ApplicationContext ctx = new ClassPathXmlApplicationContext(xmlFile);
Calculator calc = (Calculator) ctx.getBean("delegatingCalculator");
calc.add(1, 2);
fail("expected IllegalStateException");
@@ -454,7 +479,6 @@ public class GroovyScriptFactoryTests {
assertEquals("test", result);
}
public static class TestCustomizer implements GroovyObjectCustomizer {
public void customize(GroovyObject goo) {
@@ -462,8 +486,7 @@ public class GroovyScriptFactoryTests {
public Object invokeMethod(Object arg0, String mName, Object[] arg2) {
if (mName.indexOf("Missing") != -1) {
throw new IllegalStateException("Gotcha");
}
else {
} else {
return super.invokeMethod(arg0, mName, arg2);
}
}

View File

@@ -2,7 +2,5 @@ package org.springframework.scripting.groovy;
import org.springframework.scripting.ConfigurableMessenger
class GroovyMessenger implements ConfigurableMessenger {
def String message;
class GroovyMessenger extends ConcreteMessenger {
}

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.1.xsd">
<lang:groovy id="refreshableMessenger" refresh-check-delay="5000" proxy-target-class="true"
script-source="classpath:org/springframework/scripting/groovy/Messenger.groovy">
<lang:property name="message" value="Hello World!" />
</lang:groovy>
</beans>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.1.xsd">
<lang:defaults proxy-target-class="true"/>
<lang:jruby id="refreshableMessenger" refresh-check-delay="1000"
script-source="classpath:org/springframework/scripting/jruby/Messenger.rb"
script-interfaces="org.springframework.scripting.Messenger">
<lang:property name="message" value="Hello World!"/>
</lang:jruby>
</beans>