Showing posts with label configuration. Show all posts
Showing posts with label configuration. Show all posts
Wednesday, July 15, 2009

Loading beans in spring...

We developed an e-shop (a front end and a back end) as an eclipse project. The front end produces its own war and the back end a different one. Both web applications uses the same API and have differences in the GUI. A major difference is that the back end uses scheduling (quartz) and the front end not. The API is configured with spring.

We decided to configure quartz with spring and the job we needed to run with it. The result was, that the front end, using the same configuration as the back end, initialized the quartz framework and enabled its own scheduling. But that was not what we wanted to do.

The solution was simple. At the definition of a spring bean in the configuration there is an attribute in the bean tag named lazy-init. The default value for this attribute is false, and this means that the container will create a bean of that kind at the initialization process. If you give the value true, then the bean will be created only at the time when you request it.













So, the scheduler initializes in the back end, because we want it to do so, and in the front end it stays only as a bean in the spring configuration.

Another spring configuration propeblem:

I have a test case I want to run using a specific configuration file. The test case looks like this:


@ContextConfiguration(locations = {"classpath:system-test-config.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class ThohapiTests {

private final static Logger logger = Logger.getLogger(ThohapiTests.class);

@Resource(name="sampleService")
private SampleService service;

@Test
public void testSampleService() {

Worker result1 = service.storeWorker();
logger.debug(result1);
assertNotNull(result1);

Worker result2 = service.storeWorker();
logger.debug(result2);
assertNotNull(result2);

logger.debug(service.getWorker(result1.getId()));
logger.debug(service.getWorker(result2.getId()));
}

@Required
public void setSampleService(SampleService sampleService) {
this.service = sampleService;
}
}


My configuration file, where I define my sampleService is this:












org.datanucleus.jdo.JDOPersistenceManagerFactory
jdbc:hsqldb:mem:dbname
sa

org.hsqldb.jdbcDriver

true














PROPAGATION_REQUIRED,readOnly
PROPAGATION_REQUIRED,readOnly
PROPAGATION_REQUIRED,readOnly
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED






and the business beans are defined in:




















Running the test case, produces the following error:
org.springframework.beans.factory.BeanInitializationException: Property 'sampleService' is required for bean 'test.ThohapiTests'
at org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.postProcessPropertyValues(RequiredAnnotationBeanPostProcessor.java:121)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:998)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:329)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:110)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:255)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:93)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.invokeTestMethod(SpringJUnit4ClassRunner.java:130)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)

Solution:
Deleting the @Required annotation from the setter of the sampleService makes everything work fine.

I think, I have a spring configuration problem. I use eclipse with the spring tool plug-in enabled for my project. I used to have one configuration file for my business logic beans and for the test environment. Then, I decided to split the configuration file in two files, one for the test environment and one for the business logic beans, do that the second one would be the base for the actuall application.

The configuration file is system-test-config.xml













org.datanucleus.jdo.JDOPersistenceManagerFactory
jdbc:hsqldb:mem:dbname
sa

org.hsqldb.jdbcDriver

true






















PROPAGATION_REQUIRED,readOnly
PROPAGATION_REQUIRED,readOnly
PROPAGATION_REQUIRED,readOnly
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED






and the application file is application-config.xml













With this configurations files it should be working, shouldn't it? The test config xml imports the application configuration, so it should recognize the sampleDAOImpl bean defined in it. But it doesn't.

Eclipse (through the sprint tool) shows me an error:
cvc-id.1: There is no ID/IDREF binding for IDREF 'sampleDAOImpl'.

and the execution of the test has as result the following exception:
Caused by: org.xml.sax.SAXParseException: cvc-id.1: There is no ID/IDREF binding for IDREF 'sampleDAOImpl'.
at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
at org.apache.xerces.util.ErrorHandlerWrapper.error(Unknown Source)
at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
at org.apache.xerces.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(Unknown Source)
at org.apache.xerces.impl.xs.XMLSchemaValidator.reportSchemaError(Unknown Source)
at org.apache.xerces.impl.xs.XMLSchemaValidator.handleEndElement(Unknown Source)
at org.apache.xerces.impl.xs.XMLSchemaValidator.endElement(Unknown Source)
at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanEndElement(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source)
at org.springframework.beans.factory.xml.DefaultDocumentLoader.loadDocument(DefaultDocumentLoader.java:75)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:396)
... 26 more

Solution:
After searching a little bit in google, I found this. It seams that there is a difference between local declared beans and not local beans. The bean sampleDAOImpl is defined in a separate xml file, so I should reference to it not as a local bean, using the ref attribute of the property tag. That's all!