I'm exposing some services using RMI on Spring. Every service has a dependency to other service bean which does the real processing job. For example:
<bean id="accountService" class="example.AccountServiceImpl">
<!-- any additional properties, maybe a DAO? -->
</bean>
<bean id="rmiAccount" class="example.AccountRmiServiceImpl"/>
<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
<!-- does not necessarily have to be the same name as the bean to be exported -->
<property name="serviceName" value="AccountService"/>
<property name="service" ref="accountService"/>
<property name="serviceInterface" value="example.AccountService"/>
<!-- defaults to 1099 -->
<property name="registryPort" value="1199"/>
</bean>
My AccountRmiServiceImpl looks like this:
public class AccountRmiServiceImpl implements AccountRmiService {
private static final long serialVersionUID = -8839362521253363446L;
private AccountService accountService;
#Autowired
public void setAccountService(AccountService accountService) {
this.accountService = accountService;
}
}
My question is: could AccountServiceImpl be created without implementing the Serializable marker interface? If it is a case, then its reference in AccountRmiServiceImpl should be made transient. This means that it would not be serialized and transfered to the client where the RMI invocation is being made. Is it possible?
Maybe.
You could definitely mark the accountService field as transient, which would indeed stop it from being serialised and sent over RMI (or more accurately, failing to be serialised and throwing an exception). However, at this point the AccountRmiServiceImpl that's reconstructed on the other side will have a null value for its accountService, which without any other changes would almost certainly lead to a NullPointerException later.
If your AccountServiceImpl is not serialisable (in the Java sense), but you are still able to create an instance of it based on some simple serialisable information, then you're in luck. You can implement the serialisation yourself using the writeObject/readObject or writeReplace/readResolve methods (see Serializable for details).
If instances of AccountServiceImpl are not serialisable in any sense of the word (e.g. an anonymous inner class with inline logic as well as references to final local variables in its outer scope), then there's no way to send this across. What kind of object would be recreated on the other side? If this is the situation you find yourself in, you'd need to refactor your code to make the class(es) serialisable.
Related
I've got a MyAppConversionServiceFactoryBean which I'm registering like:
<bean id="conversionService" class="com.MyProject.MyAppConversionServiceFactoryBean">
<property name="messageSource" ref="messageSource"/>
<property name="converters">
<set>
<bean class="com.MyProject.XRepresentationConverter" />
<bean class="com.MyProject.YRepresentationConverter" />
<bean class="com.MyProject.ZRepresentationConverter" />
</set>
</property>
</bean>
I can continue to list every converter we write into this list, but I'd love to be able to configure it such that this isn't necessary and that converters will automatically register themselves somehow with my factory.
Sidebar 1: If that's not possible with a custom factory, is it possible with the default spring one?
Sidebar 2: If neither the first part nor Sidebar 1 is possible, is it possible to #Autowired the conversionService into the converters (so they can easily call one another)? Attempting to #Autowired ConversionService conversionService has previously given me issues due to not being able to wire the conversionService into an object while it's still busy creating the service.
Note: We're using Spring, but not Spring MVC. I have no control over that, so any solutions on that route will be unfortunately unusable. I can change pretty much anything else about the configuration and Java classes, just not the overarching tools.
#Vikdor's comment on the question pointed me in the right direction.
Spring is apparently capable (and no one I asked in person knew this) of gathering collections of beans through the scanning process with #Autowired annotations. Here's what I needed to achieve the same effect I got from the configuration in the post:
applicationContent.xml must have:
<context:component-scan base-package="com.MyProject"/>
<bean id="conversionService" class="com.MyProject.MyAppConversionServiceFactoryBean" />
MyAppConversionServiceFactoryBean.java:
public class MyAppConversionServiceFactoryBean implements
FactoryBean<ConversionService>, InitializingBean {
#Autowired
private Set<BaseConverter> converters;
}
And then all of my converters now have the #Component annotation.
Relevant Docs on #Autowired do briefly mention that it can be used to collect all beans of a type, but I wouldn't have known that it could be done into any collection type without this thread by Grzegorz Oledzki which addresses the generic form of my question, but takes it down a philosophical route.
For efficiency reasons, I am interested in limiting the number of threads that simultaneously uses the beans of the Spring application context (I don't want an unlimited number of threads proccessing in my limited memory).
I have found here (spring documentation) a way to achieve this by pooling the beans in a EJB style, by doing the following:
Declare the target bean as scope "prototype".
Declare a Pool provider that will deliver a limited number of pooled "target" instances.
Declare a "ProxyFactoryBean" which function is not clear to me.
Here is the declaration of this beans:
<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"/>
<property name="interceptorNames" value="myInterceptor"/>
</bean>
My problem is that when I will declare another bean to use pooled instances of the "businessObjectTarget", how should I do it? I mean, when i try to do something like this:
<bean id="clientBean" class="com.mycompany.ClientOfTheBusinessObject">
<property name="businessObject" ref="WHAT TO PUT HERE???"/>
</bean>
What should be the value of the "ref" ??
You cannot use properties to get instances of prototypes.
One option is to use the lookup methods (see chapter 3.3.7.1)
Another option to get your bean in code: make your com.mycompany.ClientOfTheBusinessObject to implement the ApplicationContextAware interface and then call context.getBean("clientBean")
Please note the name of the third bean in the spring example:-"businessObject"
It means this the bean from where you are supposed to access the common pool.
For your case if you need your own client bean you may have it as follows.
But in such a case businessObject is not required.:-
<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="clientBean" class="com.mycompany.ClientOfTheBusinessObject">
<property name="poolTargetSource" ref="poolTargetSource"/>
</bean>
Java classes:-
public class ClientOfTheBusinessObject{
CommonsPoolTargetSource poolTargetSource;
//<getter and setter for poolTargeTSource>
public void methodToAccessCommonPool(){
//The following line gets the object from the pool.If there is nothing left in the pool then the thread will be blocked.(The blocking can be replaced with an exception by changing the properties of the CommonsPoolTargetSource bean)
MyBusinessObject mbo = (MyBusinessObject)poolTargetSource.getTarget();
//Do whatever you want to do with mbo
//the following line puts the object back to the pool
poolTargetSource.releaseTarget(mbo);
}
}
I'm pretty sure you can limit the number of simultaneous threads in a less convoluted way. Did you look at the Java Concurrency API, specifically at the Executors.newFixedThreadPool() ?
i used java-configuration to construct a proxy over the interface that handles pooling using apache commons-pool to achieve invocation-level-pooling.
I did it using Annotations based configuration:
I did create my BusinessObject class as a POJO and annotate it this way:
#Component("businessObject")
#Scope("prototype")
public class BusinessObject { ... }
I gave it a specific name and did mark it as prototype so that Spring doesn't create a singleton instance for it; every time the bean is required, Spring would create a new instance.
In my #Configuration class (or in the #SpringBootApplication class, if using Spring Boot) I created a CommonsPool2TargetSource instance to hold BusinessObject instances:
#Bean
public CommonsPool2TargetSource pooledTargetSource() {
final CommonsPool2TargetSource commonsPoolTargetSource = new CommonsPool2TargetSource();
commonsPoolTargetSource.setTargetBeanName("businessObject");
commonsPoolTargetSource.setTargetClass(BusinessObject.class);
commonsPoolTargetSource.setMaxSize(maxPoolSize);
return commonsPoolTargetSource;
}
Here I'm indicating that the pool will hold BusinessObject instances. Notice that my maxPoolSize=? value is set with the max number of BusinessObject instances I want to hold in the pool.
Finally, I did access my pooled instances this way:
#Autowired
private CommonsPool2TargetSource pooledTargetSource;
void someMethod() {
// First I retrieve one pooled BusinessObject instance
BusinessObject businessObject = (BusinessObject)pooledTargetSource.getTarget();
try {
// Second, I do some logic using the BusinessObject instance gotten
} catch (SomePossibleException e) {
// Catch and handle any potential error, if any
} finally {
// Finally, after executing my business logic
// I release the BusinessObject instance so that it can be reused
pooledTargetSource.releaseTarget(businessObject);
}
}
It is very important to always make sure to release the BusinessObject borrowed from the pool, without mattering if the business logic did finish successfully or with error. Otherwise the pool could get empty with all the instances being borrowed and never released and any further requests for instances will block forever.
What is the benefit of distancing DAO classes from the ones actually being instantiated in the application code, i.e. why not just instantiate the dao class straight up in a scenario like this:
Class CreateIocContainer{
p s v main(String[] args){
new IocContainer("springMetadataFile.xml");
}
}
Class ClassThatInstantiatesServicesViaSpringBean{
Services services;
// bean setter for services class
setServices(Services services){
this.services = services
}
}
Class ServicesImpl implements Services
ServicesDao servicesDao;
String getSomethingFromDB(String argumentForQuery){
return servicesDao.getSomethingFromDB(argumentForQuery);
}
}
Class ServicesDaoImpl implements ServicesDao{
String getSomethingFromDb(String argumentForQuery){
//code to return something from db
return queryResultString;
}
}
Also, would the class I called Class ClassThatInstantiatesServicesViaSpringBean be a factory class and usually be named Class XFactory?
Your DAOs are always interfaces they are never a class. This DAO is basically a design pattern. This separation of DAO and its implementation gives a nice technique for separating object persistence mechanism and data access logic.
Today in the bean xml file you mention,
<bean name="ServiveDao" class="com.example.ServiceImplHibnernate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
But tomorrow you may want your application to use different implementation done by you without changing the client code. For example, you have rewritten the implementation using ibatis with additional features to match up your requirement. So you write a class
class ServiceImplIBAtis implements ServiceDao {..}
and change the xml file to load your implementation
<bean name="ServiveDao" class="com.mycompany.ServiceImplIBAtis">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
Where ever the bean ServiceDao is referenced the spring will inject the ServiceImplIBAtis instance instead of ServiceImplHibnernate. Now your application does not need to know what is changed in the background. All it needs to know is there is a dao called Service and there are methods that can be used for data access.
I have a static method I have no control over: MyUtils.getServiceURL() which returns a URL. I need to extract just the port from this URL to set a property on a bean:
<bean id="myBean>
<property name="defaultPort" value="?????"/>
</bean>
I can get the string value of the URL as a bean like this:
<bean id="serviceURL" class="MyUtils" factory-method="getServiceURL" />
I'm probably just going to write a method to parse the URL in myBean and extract the port. I was wondering if there was a way to avoid having to do this, and configure this directly in the spring context?
No need for custom classes, or parsers. Remember, a bean is just a class with get/is/set methods. A java.net.URL class qualifies as such.
Solution: Use a java.net.URL as a Spring-configurable bean and call it's getPort method.
Remember, in Spring, you can wire anything as a bean very easily so long as it sports methods using the get/is/set Bean convention. The java.net.URL class does such a thing.
** warning ** I'm just typing this out of my a$$, you'll have to check for any syntax shenanigans that I might be introducing in this Spring-config pseudo-code. One thing that is certain is that the concept will work with Spring 2.5 and that it relies on the util schema.
If you are using an older version of Spring, you'll have to use a PropertyPathFactoryBean. If you are using Spring 3.0, you'll want to use Spring expression language (EL), but I can't comment on the later since I'm not familiar with Spring 3.0.
In java:
int port = (new URL(MyUtils.getServiceURL()).getPort()
In Spring:
<bean id="serviceURL" class="MyUtils" factory-method="getServiceURL" />
<bean id="myURL" class="java.net.URL">
<constructor-arg>
<ref-bean="serviceURL"/>
</constructor-arg>
</bean>
<util:property-path id="defaultPort" path="myURL.port"/>
<bean id="myBean>
<property name="defaultPort" ref="defaultPort"/>
</bean>
There might be a way to consolidate all these four expressions into three or less, don't know if that will improve readability, though. The concept remains the same, though. Treat a java.net.URL instance as a bean, set its URL via its constructor, and get a hold (via Spring) of its getPort() method.
** edit **:
If you are using Spring 2.5 you can create an inline groovy bean that does all that for you. I've seen people doing that as integration glue to get rid of multitude of temp Spring bean place holders. That's the best choice IMO when you need to define a class (when it's simpler than just using Spring tags) and when you know such a class won't be used outside of Spring wiring of things.
Not I can think of. Either way, you probably have to write something to parse the port out. Since you have no control of that static method, perhaps you may want to utilize the adapter pattern to hide that static method. Doing so also makes your code easier to test because you can easily mock that external API out. For example:-
public interface URLServiceAdapter {
int getServiceURLPort();
}
public class URLServiceAdapterImpl implements URLServiceAdapter {
public int getServiceURLPort() {
return MyUtils.getServiceURL().getPort();
}
}
Your beans will then rely on your adapter class instead of MyUtils.getServiceURL() directly:-
<bean id="urlServiceAdapter" class="project.URLServiceAdapterImpl" />
That way, you can do something like this:-
#Autowired
private UrlServiceAdapter urlServiceAdapter;
...
bean.setDefaultPort(urlServiceAdapter.getServiceURLPort());
SpEL is your friend.
<bean id="myBean>
<property name="defaultPort"
value='#{ T(com.foo.MyUtils).getServiceURL().split(":")[2].split("/")[0] }'/>
</bean>
Enjoy,
Using Spring and Hibernate, I want to write to one MySQL master database, and read from one more more replicated slaves in cloud-based Java webapp.
I can't find a solution that is transparent to the application code. I don't really want to have to change my DAOs to manage different SessionFactories, as that seems really messy and couples the code with a specific server architecture.
Is there any way of telling Hibernate to automatically route CREATE/UPDATE queries to one datasource, and SELECT to another? I don't want to do any sharding or anything based on object type - just route different types of queries to different datasources.
An example can be found here: https://github.com/afedulov/routing-data-source.
Spring provides a variation of DataSource, called AbstractRoutingDatasource. It can be used in place of standard DataSource implementations and enables a mechanism to determine which concrete DataSource to use for each operation at runtime. All you need to do is to extend it and to provide an implementation of an abstract determineCurrentLookupKey method. This is the place to implement your custom logic to determine the concrete DataSource. Returned Object serves as a lookup key. It is typically a String or en Enum, used as a qualifier in Spring configuration (details will follow).
package website.fedulov.routing.RoutingDataSource
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class RoutingDataSource extends AbstractRoutingDataSource {
#Override
protected Object determineCurrentLookupKey() {
return DbContextHolder.getDbType();
}
}
You might be wondering what is that DbContextHolder object and how does it know which DataSource identifier to return? Keep in mind that determineCurrentLookupKey method will be called whenever TransactionsManager requests a connection. It is important to remember that each transaction is "associated" with a separate thread. More precisely, TransactionsManager binds Connection to the current thread. Therefore in order to dispatch different transactions to different target DataSources we have to make sure that every thread can reliably identify which DataSource is destined for it to be used. This makes it natural to utilize ThreadLocal variables for binding specific DataSource to a Thread and hence to a Transaction. This is how it is done:
public enum DbType {
MASTER,
REPLICA1,
}
public class DbContextHolder {
private static final ThreadLocal<DbType> contextHolder = new ThreadLocal<DbType>();
public static void setDbType(DbType dbType) {
if(dbType == null){
throw new NullPointerException();
}
contextHolder.set(dbType);
}
public static DbType getDbType() {
return (DbType) contextHolder.get();
}
public static void clearDbType() {
contextHolder.remove();
}
}
As you see, you can also use an enum as the key and Spring will take care of resolving it correctly based on the name. Associated DataSource configuration and keys might look like this:
....
<bean id="dataSource" class="website.fedulov.routing.RoutingDataSource">
<property name="targetDataSources">
<map key-type="com.sabienzia.routing.DbType">
<entry key="MASTER" value-ref="dataSourceMaster"/>
<entry key="REPLICA1" value-ref="dataSourceReplica"/>
</map>
</property>
<property name="defaultTargetDataSource" ref="dataSourceMaster"/>
</bean>
<bean id="dataSourceMaster" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="${db.master.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</bean>
<bean id="dataSourceReplica" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="${db.replica.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</bean>
At this point you might find yourself doing something like this:
#Service
public class BookService {
private final BookRepository bookRepository;
private final Mapper mapper;
#Inject
public BookService(BookRepository bookRepository, Mapper mapper) {
this.bookRepository = bookRepository;
this.mapper = mapper;
}
#Transactional(readOnly = true)
public Page<BookDTO> getBooks(Pageable p) {
DbContextHolder.setDbType(DbType.REPLICA1); // <----- set ThreadLocal DataSource lookup key
// all connection from here will go to REPLICA1
Page<Book> booksPage = callActionRepo.findAll(p);
List<BookDTO> pContent = CollectionMapper.map(mapper, callActionsPage.getContent(), BookDTO.class);
DbContextHolder.clearDbType(); // <----- clear ThreadLocal setting
return new PageImpl<BookDTO>(pContent, p, callActionsPage.getTotalElements());
}
...//other methods
Now we can control which DataSource will be used and forward requests as we please. Looks good!
...Or does it? First of all, those static method calls to a magical DbContextHolder really stick out. They look like they do not belong the business logic. And they don't. Not only do they not communicate the purpose, but they seem fragile and error-prone (how about forgetting to clean the dbType). And what if an exception is thrown between the setDbType and cleanDbType? We cannot just ignore it. We need to be absolutely sure that we reset the dbType, otherwise Thread returned to the ThreadPool might be in a "broken" state, trying to write to a replica in the next call. So we need this:
#Transactional(readOnly = true)
public Page<BookDTO> getBooks(Pageable p) {
try{
DbContextHolder.setDbType(DbType.REPLICA1); // <----- set ThreadLocal DataSource lookup key
// all connection from here will go to REPLICA1
Page<Book> booksPage = callActionRepo.findAll(p);
List<BookDTO> pContent = CollectionMapper.map(mapper, callActionsPage.getContent(), BookDTO.class);
DbContextHolder.clearDbType(); // <----- clear ThreadLocal setting
} catch (Exception e){
throw new RuntimeException(e);
} finally {
DbContextHolder.clearDbType(); // <----- make sure ThreadLocal setting is cleared
}
return new PageImpl<BookDTO>(pContent, p, callActionsPage.getTotalElements());
}
Yikes >_< ! This definitely does not look like something I would like to put into every read only method. Can we do better? Of course! This pattern of "do something at the beginning of a method, then do something at the end" should ring a bell. Aspects to the rescue!
Unfortunately this post has already gotten too long to cover the topic of custom aspects. You can follow up on the details of using aspects using this link.
I don't think that deciding that SELECTs should go to one DB (one slave) and CREATE/UPDATES should go to a different one (master) is a very good decision. The reasons are:
replication is not instantaneous, so you could CREATE something in the master DB and, as part of the same operation, SELECT it from the slave and notice that the data hasn't yet reached the slave.
if one of the slaves is down, you shouldn't be prevented from writing data in the master, because as soon as the slave is back up, its state will be synchronized with master. In your case though, your write operations are dependent on both master and slave.
How would you then define transactionality if you're in fact using 2 dbs?
I would advise using the master DB for all the WRITE flows, with all the instructions they might require (whether they are SELECTs, UPDATE or INSERTS). Then, the application dealing with the read-only flows can read from the slave DB.
I'd also advise having separate DAOs, each with its own methods, so that you'll have a clear distinction between read-only flows and write/update flows.
You could create 2 session factories and hava a BaseDao wrapping the 2 factories(or the 2 hibernateTemplates if you use them) and use the get methods with on factory and the saveOrUpdate methods with the other
Try this way : https://github.com/kwon37xi/replication-datasource
It works nicely and very easy to implement without any extra annotation or code. It requires only #Transactional(readOnly=true|false).
I have been using this solution with Hibernate(JPA),Spring JDBC Template, iBatis.
You can use DDAL to implement writting master database and reading slave database in a DefaultDDRDataSource without modifying your Daos, and what's more, DDAL provided loading balance for mulit-slave databases. It doesn't rely on spring or hibernate. There is a demo project to show how to use it: https://github.com/hellojavaer/ddal-demos and the demo1 is just what you described scene.