How do I actually use a Spring pooled object? - java

I am working through an example of spring pooling described here.
http://docs.spring.io/spring/docs/2.0.0/reference/aop-api.html#aop-ts-pool
I have read through a very similar question here, but still don't have an answer.
How to use Pooled Spring beans instead of Singleton ones?
Assuming I have the following beans defined in my SpringConfig file, how do I actually use the pooled objects?
<bean id="businessObjectTarget" class="com.mycompany.MyBusinessObject" scope="prototype">
... properties omitted
</bean>
<bean id="poolTargetSource" class="org.springframework.aop.target.CommonsPoolTargetSource">
<property name="targetBeanName" value="businessObjectTarget"/>
<property name="maxSize" value="25"/>
</bean>
<bean id="businessObject" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="targetSource" ref="poolTargetSource"/>
</bean>
I am doing something like this but I have no idea how to tell if it working.
#Resource(name = "businessObject")
private MyBusinessObject businessObject;
...
method() {
...
businessObject.method();
...
}
How am I actually supposed to use the pooled object?
Thanks.
PS - I am even less sure of it working now. I made the following change and submitted two threads. The first one worked, the second one got an error indicative of simultaneous use:
<bean id="poolTargetSource" class="org.springframework.aop.target.CommonsPoolTargetSource">
<property name="targetBeanName" value="businessObjectTarget" />
<property name="maxSize" value="1" />
<property name="whenExhaustedActionName" value="WHEN_EXHAUSTED_FAIL" />
</bean>
I am very skeptical.

Related

Spring batch - overriding jobrepository in context.xml

Like described in the linked article below, with Java configuration it is possible to override the JobRepository bean by extending DefaultBatchConfigurer and overriding createJobRepository.
How can this be achieved in a context.xml file where the jobrepository bean is defined like this
<bean id="jobRepository_new"
class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
<property name="databaseType" value="Oracle" />
<property name="dataSource" ref="dataSource-batch" />
<property name="transactionManager" ref="transactionManager" />
<property name="tablePrefix" value="BATCH_" />
<property name="lobHandler" ref="oracleLobHandler" />
</bean>
?
Can't serialize access for this transaction when running single job, SERIALIZED isolation level
Unlike with the Java configuration style, there is nothing provided by default (that you can override) when you use the XML configuration style.
So you just need configure the job repository bean as needed like shown in the snippet you shared.

DAO null in spring bean class with xml config

I'm trying to inject the uploadDao in the bean DemoHandler (XML below). But as expected it is Null. The question is how do I inject the DAO correctly.
Right now, there is a method call from WebUploadServiceImpl to DemoHandler and I can add 1 more parameter and send the value I need from uploadDao, but then that method is reused for multiple java classes and all those methods need to be refactored and that new param will not be relevant to the other classes.
Is there a way to get uploadDao to inject in DemoHandler? Any help is much appreciated. Thanks
Spring XML:
<bean id="wuService" class="com.abcd.service.WebUploadServiceImpl">
<property name="uploadDao" ref="uploadDao" />
<property name="webHandlers">
<set>
<bean class="com.abcd.service.handler.DemoHandler" />
</set>
</property>
</bean>
Code:
public class DemoHandler {
private UploadDao uploadDao;
public List handleM(...) {
...
Period period = uploadDao.anyMethod(..); --- Null here
}
}
If DemoHandler needs to set a dao, why don't you do something like this ...
<bean id="uploadDao" class="whatever.dao.UploadDaoImpl"/>
<bean id="wuService" class="com.abcd.service.WebUploadServiceImpl">
<property name="uploadDao" ref="uploadDao" />
<property name="webHandlers">
<set>
<bean class="com.abcd.service.handler.DemoHandler">
<property name="uploadDao" ref="uploadDao" />
</bean>
</set>
</property>
</bean>
You just need to replicate the injection mechanism already used in WebUploadServiceImpl. You haven't shown that code, I don´t know if you use #Autowired, a set method or any other possibility.

Creating multiple bean instances of a class with different property values in spring configuration

I am creating multiple bean instances of a class with different property values in spring configuration.
For example:
<bean id="myBeanA" class="MyClass">
<property name="identifier" value="A"/>
</bean>
<bean id="myBeanY" class="MyClass">
<property name="identifier" value="B"/>
</bean>
I am new to Spring framework and I am just curious to know the pros and cons to doing this.
of course you can (as you already show - ignoring typo). Pros/Cons? None, you just do it if it make sense for you...
<bean id="primaryService" class="MyService">
<property name="url" value="http://domain1/"/>
</bean>
<bean id="premiumService" class="MyService">
<property name="url" value="http://domain2/"/>
</bean>
E.g. you can have two instances of the same service type, but accessing different remote URL. You can use premiumService only for paying customers as kind of quality of service (e.g. domain2 is stronger machine)

How to initialize in-memory HSQLDB using script via Spring

I am attempting to do unit testing of my DAO (using Spring and Hibernate). I am using HSQLDB per this tutorial. The tutorial states that the in-memory HSQLDB database can be initialized using a SQL script but I cannot find information on how to do so in Spring. Here is the pertinent Spring context config:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:mem:mydb" />
<property name="username" value="sa" />
<property name="password" value="" />
<property name="initialSize" value="5" />
<property name="maxActive" value="10" />
<property name="poolPreparedStatements" value="true" />
<property name="maxOpenPreparedStatements" value="10" />
</bean>
Any help would be appreciated. Thanks.
If you are trying to work with in-memory databases and Spring, there is a new jdbc namespace for Spring 3 that makes working with embedded databases very easy.
The best part is that it acts as a DataSource, so it can easily be dropped in to replace your existing dataSource bean.
<jdbc:embedded-database id="dataSource" type="HSQL">
<jdbc:script location="classpath:schema.sql"/>
<jdbc:script location="classpath:test-data.sql"/>
</jdbc:embedded-database>
If you are more interested in doing this with Java Config, take a look at the EmbeddedDatabaseBuilder (new in Spring 3.0).
#Configuration
public class DatabaseTestConfig {
#Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:schema.sql")
.addScript("classpath:test-data.sql")
.build();
}
}
Nicholas answer is perfectly fine, but you can use jdbc namespace to initialize external database as well:
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/DS"/>
<jdbc:initialize-database data-source="dataSource">
<jdbc:script location="classpath:/META-INF/database/init.sql"/>
</jdbc:initialize-database>
In the tutorial you link to, one of the ways of setting things up is this (after obvious correction):
In-memory from a script: jdbc:hsqldb:file:path-to-file
I think that that would appear to be relevant. I suggest replacing path-to-file with something that looks like a fully-qualified filename…
You could get around this by creating a subclass of BasicDataSource with getters/setters for two new properties, initExecuteSqlFile and destroyExecuteSqlFile, that can have a comma-seperated list of SQL files to execute. The subclass would have init() and destroy() methods that handle the init/destroy SQL files.
Then use the following bean definition:
<bean
id="datasource"
class="com.example.MyBasicDataSource"
destroy-method="destroy"
init-method="init"
>
<property name="destroyExecuteSqlFile">
<value>h2-destroy-01.sql</value>
</property>
<property name="initExecuteSqlFile">
<value>h2-init-01.sql,h2-init-02.sql,h2-init-03.sql</value>
</property>
<!-- Other properties -->
</bean>
With embedded-database we would only be able to connect to the database from the same JVM. If we have two JVMs, for performance or other constraints, we can:
Instead of using an embedded-database, you can use the datasource suggested in this answer.
Then initialize like Poitrek De suggested (and suggested in previous answer too). You may want to create tables only if they do not exist (as suggested here).

Using a DAO on a Bean used by a Spring Scheduled Task

I'm developing a web application using Struts2 + Spring, and now I'm trying to add a scheduled task. I'm using Spring's task scheduling to do so. In my applicationContext I have:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
...
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="MYSQL" />
</bean>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
And then I have my DAO that uses this entityManagerFactory:
<bean id="dao" class="data.GenericDAO" />
So this works flawlessly within the web application. But now I have a problem when creating the scheduled task:
<task:scheduled-tasks scheduler="notifier">
<task:scheduled ref="emailService" method="sendMail" fixed-rate="30000" />
</task:scheduled-tasks>
<task:scheduler id="notifier" pool-size="10" />
<bean id="emailService" class="services.emailService" >
<property name="dao" ref="dao" />
</bean>
This executes the method sendMail on my emailService class every 30 seconds. And my emailService has the DAO injected correctly. The thing is that I can fetch objects with my DAO using the findById named queries, but when I try to access any property mapped by Hibernate, such as related collections or entities, I get an "LazyInitializationException: could not initialize proxy - no Session ". I don't know what's wrong, since I believe the scheduled task is being managed by Spring, so it should have no problem using a Spring managed DAO. I must say that I'm using the openSessionInView filter on my struts actions, so maybe I need something similar for this scheduled task.
Any help or suggestion will be appreciated, thanks!
Edit: Finally I found a way to fix this. I changed my regular Dao with one where I can decide when to start and commit the transaction. So before doing anything I start a transaction and then everything works OK. So I still don't know exactly what causes the problem and if someday I'll be able to use my regular DAO, for the moment I'm staying with this solution.
OpenSessionInView won't help you, because you don't have a web context. You need Spring's Declarative Transaction Management.
In most cases, what you need to do is just this XML:
<!-- JPA, not hibernate -->
<bean id="myTxManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven transaction-manager="myTxManager" />
<!-- without backing interfaces you probably also need this: -->
<aop:config proxy-target-class="true">
(Annotate your EmailService class as #Transactional to enable this)

Categories