I wanted to have access to my POJO's and local interfaces to ejb's from other ejb's using one single Spring application context within the Jboss container..
I have created a Spring MBean,- running a standalone MBean service....
// deployed the class within a jar into the jboss lib folder...Code:package no.aftenposten.framework.spring; import org.jboss.naming.NonSerializableFactory; import org.jboss.system.ServiceMBeanSupport; import org.springframework.context.ApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext; import javax.naming.*; import java.io.*; import java.util.Properties; /** * JMX - MBean which initiates the Spring framework by reading the spring.xml, exposing * the Spring ApplicationContext from withing the ejb-container via jndi lookup. * see spring-service.xml * * <p/> * User: regearne * Date: 03.des.2004 * Time: 15:02:51 * * @author regearne * @version $Revision: 1.2 $Date: 2005/01/01 19:31:52 $ */ public class SpringService extends ServiceMBeanSupport implements SpringServiceMBean { private Properties properties; private String jndiName; private String propertiesFile; private boolean useProperties; private boolean usePropertiesFile; ApplicationContext context = null; private static final String SPRING_CONFIG_KEY = "spring.config"; /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Constructors. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ public SpringService() { usePropertiesFile = false; propertiesFile = ""; useProperties = false; properties = new Properties(); jndiName = "Spring"; } /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Interface. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ public void setJndiName(String jndiName) throws Exception { String oldName = this.jndiName; this.jndiName = jndiName; if (super.getState() == STARTED){ try { unbind(oldName); } catch (NamingException ne) { log.error(captureStackTrace(ne)); throw new Exception("Failed to unbind Spring - ", ne); } try { rebind(); } catch (NamingException ne) { log.error(captureStackTrace(ne)); throw new Exception("Failed to rebind Spring - ", ne); } } } /** Getter for jndiName * * @return */ public String getJndiName() { return jndiName; } /** Getter for name * * @return */ public String getName() { return "SpringService(" + jndiName + ")"; } /** Setter for properties, - used when assign properties via the * spring-service.xml * * @param properties */ public void setProperties(String properties) { if (usePropertiesFile){ log.error("Must specify only one of 'Properties' or 'PropertiesFile'"); return; } useProperties = true; try { ByteArrayInputStream bais = new ByteArrayInputStream(properties.getBytes()); this.properties = new Properties(); this.properties.load(bais); } catch (IOException ioe) { // should not happen } } /** Get properties * * @return */ public String getProperties() { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); properties.store(baos, ""); return new String(baos.toByteArray()); } catch (IOException ioe) { // should not happen return ""; } } /** Setter for propertiesFile * * @param propertiesFile */ public void setPropertiesFile(String propertiesFile) { if (useProperties){ log.error("Must specify only one of 'Properties' or 'PropertiesFile'"); return; } usePropertiesFile = true; this.propertiesFile = propertiesFile; } public String getPropertiesFile() { return propertiesFile; } public void createService() throws Exception { } public void destroyService() throws Exception { log.info("Destroy SpringService(" + jndiName + ")..."); } /** Starting the jmx-service * * @throws Exception */ public void startService() throws Exception { log.info("Start SpringService(" + jndiName + ")..."); String configFile; if ((configFile = properties.getProperty(SPRING_CONFIG_KEY)) != null){ if (new File(configFile).exists()){ log.info("Initializing Spring framework with " + configFile); context = new FileSystemXmlApplicationContext(configFile); log.info("Spring framework initialized"); } else { throw new FileNotFoundException("File: "+configFile+"doesn't exist"); } } try { rebind(); } catch (NamingException ne) { log.error(captureStackTrace(ne)); throw new Exception("Failed to rebind Spring - ", ne); } log.info("SpringService(" + jndiName + ") started."); } public void stopService() throws Exception { log.info("Stop SpringService(" + jndiName + ")..."); log.info("Spring(" + jndiName + ") stopped."); } private String captureStackTrace(Throwable throwable) { StringWriter sw = new StringWriter(); throwable.printStackTrace(new PrintWriter(sw, true)); return sw.toString(); } private static Context createContext(Context rootCtx, Name name) throws NamingException { Context subctx = rootCtx; for (int n = 0; n < name.size(); n++){ String atom = name.get(n); try { Object obj = subctx.lookup(atom); subctx = (Context) obj; } catch (NamingException e) { // No binding exists, create a subcontext subctx = subctx.createSubcontext(atom); } } return subctx; } private void rebind() throws Exception { InitialContext rootCtx = new InitialContext(); // Get the parent context into which we are to bind Name fullName = rootCtx.getNameParser("").parse(jndiName); Name parentName = fullName; if (fullName.size() > 1){ parentName = fullName.getPrefix(fullName.size() - 1); } else { parentName = new CompositeName(); } Context parentCtx = createContext(rootCtx, parentName); Name atomName = fullName.getSuffix(fullName.size() - 1); String atom = atomName.get(0); // Scheduler scheduler = schedulerFactory.getScheduler(); NonSerializableFactory.rebind(parentCtx, atom, context); } private void unbind(String jndiName) throws NamingException { Context rootCtx = new InitialContext(); Name fullName = rootCtx.getNameParser("").parse(jndiName); Name atomName = fullName.getSuffix(fullName.size() - 1); String atom = atomName.get(0); rootCtx.unbind(jndiName); NonSerializableFactory.unbind(atom); } }
and a spring-service.xml into the deploy folder, firing up the the service into the Jboss....
This enables me through this static method from any ejb to access the Spring application context within the container...Code:<?xml version="1.0" encoding="UTF-8"?> <server> <classpath codebase="." archives="a-framework.jar"/> <mbean code="no.aftenposten.framework.spring.SpringService" name="user:service=SpringService,name=SpringService"> <attribute name="JndiName">Spring</attribute> <attribute name="Properties"> spring.config=/jboss-3.2.2/server/default/deploy/spring.xml </attribute> </mbean> </server>
From my ejb, - the only code I need to access a Spring configured bean is:Code:public static Object getBean(String name) throws NamingException, ComponentNotAvailableException { //Initializing the spring configuration InitialContext jndiContext = new InitialContext(); ApplicationContext context; if((context = (ApplicationContext) jndiContext.lookup("Spring")) != null){ return context.getBean(name); } else { throw new ComponentNotAvailableException("Could get Spring-bean-"+name+"," + " due to missing BeanFactory (jndi-Spring)"); } }
What about this way of implementing the Spring into ejb container. Have I overlooked something. I haven't found any standard Spring classes helping my to achieve the same solution, - which I would have preferred. Or should I solve it another way??Code:HibernateDAO sf = (HibernateDAO) SpringBeanFactory.getBean("DAOImplementation"); sf.create(bean);
Geir


Reply With Quote
.
