Skip to content

Commit

Permalink
Restore outdated local/remote-slsb attributes for declaration compati…
Browse files Browse the repository at this point in the history
…bility

Legacy EJB attributes are ignored since 6.0 due to being bound to a plain JndiObjectFactoryBean - but can still be declared now, e.g. when validating against the common versions of spring-jee.xsd out there.

Closes gh-31627

(cherry picked from commit 6955598)
  • Loading branch information
jhoeller committed Nov 20, 2023
1 parent 0fc3811 commit 0ee3609
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2023 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.
Expand All @@ -18,12 +18,13 @@

import org.w3c.dom.Element;

import org.springframework.beans.BeanUtils;
import org.springframework.jndi.JndiObjectFactoryBean;

/**
* {@link org.springframework.beans.factory.xml.BeanDefinitionParser}
* implementation for parsing '{@code local-slsb}' tags and
* creating plain {@link JndiObjectFactoryBean} definitions.
* creating plain {@link JndiObjectFactoryBean} definitions on 6.0.
*
* @author Rob Harrop
* @author Juergen Hoeller
Expand All @@ -36,4 +37,10 @@ protected Class<?> getBeanClass(Element element) {
return JndiObjectFactoryBean.class;
}

@Override
protected boolean isEligibleAttribute(String attributeName) {
return (super.isEligibleAttribute(attributeName) &&
BeanUtils.getPropertyDescriptor(JndiObjectFactoryBean.class, extractPropertyName(attributeName)) != null);
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2023 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.
Expand All @@ -18,12 +18,13 @@

import org.w3c.dom.Element;

import org.springframework.beans.BeanUtils;
import org.springframework.jndi.JndiObjectFactoryBean;

/**
* {@link org.springframework.beans.factory.xml.BeanDefinitionParser}
* implementation for parsing '{@code remote-slsb}' tags and
* creating plain {@link JndiObjectFactoryBean} definitions.
* creating plain {@link JndiObjectFactoryBean} definitions as of 6.0.
*
* @author Rob Harrop
* @author Juergen Hoeller
Expand All @@ -36,4 +37,10 @@ protected Class<?> getBeanClass(Element element) {
return JndiObjectFactoryBean.class;
}

@Override
protected boolean isEligibleAttribute(String attributeName) {
return (super.isEligibleAttribute(attributeName) &&
BeanUtils.getPropertyDescriptor(JndiObjectFactoryBean.class, extractPropertyName(attributeName)) != null);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -95,23 +95,64 @@
</xsd:complexType>
</xsd:element>

<xsd:element name="local-slsb" type="jndiLocatingType">
<xsd:element name="local-slsb" type="ejbType">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.jndi.JndiObjectFactoryBean"><![CDATA[
Exposes a reference to a local EJB Stateless SessionBean.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>

<xsd:element name="remote-slsb" type="jndiLocatingType">
<xsd:element name="remote-slsb">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.jndi.JndiObjectFactoryBean"><![CDATA[
Exposes a reference to a remote EJB Stateless SessionBean.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="ejbType">
<xsd:attribute name="home-interface" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:java.lang.Class"><![CDATA[
The home interface that will be narrowed to before performing the
parameterless SLSB create() call that returns the actual SLSB proxy.
NOTE: Effectively ignored as of 6.0 in favor of plain JNDI lookups.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="refresh-home-on-connect-failure" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Controls whether to refresh the EJB home on connect failure.
NOTE: Effectively ignored as of 6.0 in favor of plain JNDI lookups.
Can be turned on to allow for hot restart of the EJB server.
If a cached EJB home throws an RMI exception that indicates a
remote connect failure, a fresh home will be fetched and the
invocation will be retried.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="cache-session-bean" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Controls whether to cache the actual session bean object.
NOTE: Effectively ignored as of 6.0 in favor of plain JNDI lookups.
Off by default for standard EJB compliance. Turn this flag
on to optimize session bean access for servers that are
known to allow for caching the actual session bean object.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>

<xsd:complexType name="jndiLocatingType">
<!-- base types -->
<xsd:complexType name="jndiLocatingType" abstract="true">
<xsd:complexContent>
<xsd:extension base="beans:identifiedType">
<xsd:sequence>
Expand Down Expand Up @@ -183,6 +224,40 @@
</xsd:complexContent>
</xsd:complexType>

<xsd:complexType name="ejbType">
<xsd:complexContent>
<xsd:extension base="jndiLocatingType">
<xsd:attribute name="lookup-home-on-startup" type="xsd:boolean" default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[
Controls whether the lookup of the EJB home object is performed
immediately on startup (if true, the default), or on first access
(if false).
NOTE: Effectively ignored as of 6.0 in favor of plain JNDI lookups.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="cache-home" type="xsd:boolean" default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[
Controls whether the EJB home object is cached once it has been located.
On by default; turn this flag off to always reobtain fresh home objects.
NOTE: Effectively ignored as of 6.0 in favor of plain JNDI lookups.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="business-interface" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:java.lang.Class"><![CDATA[
The business interface of the EJB being proxied.
NOTE: Effectively ignored as of 6.0 in favor of plain JNDI lookups.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>

<xsd:simpleType name="environmentRefType">
<xsd:annotation>
<xsd:appinfo>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2023 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.
Expand All @@ -16,9 +16,12 @@

package org.springframework.ejb.config;

import javax.naming.NoInitialContextException;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.RuntimeBeanReference;
Expand All @@ -29,6 +32,7 @@
import org.springframework.jndi.JndiObjectFactoryBean;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;

/**
* @author Rob Harrop
Expand Down Expand Up @@ -93,13 +97,43 @@ public void testSimpleLocalSlsb() {
BeanDefinition beanDefinition = this.beanFactory.getMergedBeanDefinition("simpleLocalEjb");
assertThat(beanDefinition.getBeanClassName()).isEqualTo(JndiObjectFactoryBean.class.getName());
assertPropertyValue(beanDefinition, "jndiName", "ejb/MyLocalBean");

assertThatExceptionOfType(BeanCreationException.class)
.isThrownBy(() -> this.beanFactory.getBean("simpleLocalEjb"))
.withCauseInstanceOf(NoInitialContextException.class);
}

@Test
public void testSimpleRemoteSlsb() {
BeanDefinition beanDefinition = this.beanFactory.getMergedBeanDefinition("simpleRemoteEjb");
assertThat(beanDefinition.getBeanClassName()).isEqualTo(JndiObjectFactoryBean.class.getName());
assertPropertyValue(beanDefinition, "jndiName", "ejb/MyRemoteBean");

assertThatExceptionOfType(BeanCreationException.class)
.isThrownBy(() -> this.beanFactory.getBean("simpleRemoteEjb"))
.withCauseInstanceOf(NoInitialContextException.class);
}

@Test
public void testComplexLocalSlsb() {
BeanDefinition beanDefinition = this.beanFactory.getMergedBeanDefinition("complexLocalEjb");
assertThat(beanDefinition.getBeanClassName()).isEqualTo(JndiObjectFactoryBean.class.getName());
assertPropertyValue(beanDefinition, "jndiName", "ejb/MyLocalBean");

assertThatExceptionOfType(BeanCreationException.class)
.isThrownBy(() -> this.beanFactory.getBean("complexLocalEjb"))
.withCauseInstanceOf(NoInitialContextException.class);
}

@Test
public void testComplexRemoteSlsb() {
BeanDefinition beanDefinition = this.beanFactory.getMergedBeanDefinition("complexRemoteEjb");
assertThat(beanDefinition.getBeanClassName()).isEqualTo(JndiObjectFactoryBean.class.getName());
assertPropertyValue(beanDefinition, "jndiName", "ejb/MyRemoteBean");

assertThatExceptionOfType(BeanCreationException.class)
.isThrownBy(() -> this.beanFactory.getBean("complexRemoteEjb"))
.withCauseInstanceOf(NoInitialContextException.class);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,41 @@
</util:properties>

<!-- Local EJB Tests -->
<jee:local-slsb id="simpleLocalEjb" jndi-name="ejb/MyLocalBean"/>
<jee:local-slsb id="simpleLocalEjb" jndi-name="ejb/MyLocalBean"
business-interface="org.springframework.beans.testfixture.beans.ITestBean"/>

<jee:local-slsb id="complexLocalEjb"
jndi-name="ejb/MyLocalBean"
business-interface="org.springframework.beans.testfixture.beans.ITestBean"
cache-home="true"
lookup-home-on-startup="true"
resource-ref="true">
<jee:environment>foo=bar</jee:environment>
</jee:local-slsb>

<!-- Remote EJB Tests -->
<jee:remote-slsb id="simpleRemoteEjb" jndi-name="ejb/MyRemoteBean"/>
<jee:remote-slsb id="simpleRemoteEjb" jndi-name="ejb/MyRemoteBean"
business-interface="org.springframework.beans.testfixture.beans.ITestBean"/>

<!-- Lazy beans Tests-->
<jee:remote-slsb id="complexRemoteEjb"
jndi-name="ejb/MyRemoteBean"
business-interface="org.springframework.beans.testfixture.beans.ITestBean"
cache-home="true"
lookup-home-on-startup="true"
resource-ref="true"
home-interface="org.springframework.beans.testfixture.beans.ITestBean"
refresh-home-on-connect-failure="true"
cache-session-bean="true">
<jee:environment>foo=bar</jee:environment>
</jee:remote-slsb>

<!-- Lazy Lookup Tests-->
<jee:jndi-lookup id="lazyDataSource" jndi-name="jdbc/MyDataSource" lazy-init="true"/>
<jee:local-slsb id="lazyLocalBean" jndi-name="ejb/MyLocalBean" lazy-init="true"/>
<jee:remote-slsb id="lazyRemoteBean" jndi-name="ejb/MyRemoteBean" lazy-init="true"/>

<jee:local-slsb id="lazyLocalBean" jndi-name="ejb/MyLocalBean"
business-interface="org.springframework.beans.testfixture.beans.ITestBean" lazy-init="true"/>

<jee:remote-slsb id="lazyRemoteBean" jndi-name="ejb/MyRemoteBean"
business-interface="org.springframework.beans.testfixture.beans.ITestBean" lazy-init="true"/>

</beans>

0 comments on commit 0ee3609

Please sign in to comment.