First, please let me introduce a minimal scene demo to explain the problem.
Let's say i have a strategy pattern interface.
public interface CollectAlgorithm<T> {
public List<T> collect();
}
And a implementation of this strategy, the ConcreteAlgorithm.
public class ConcreteAlgorithm implements CollectAlgorithm<Integer> {
#Resource
QueryService queryService;
#Override
public List<Integer> collect() {
// dummy ...
return Lists.newArrayList();
}
}
As you can see, the implementation depend on some query operation provided by a #Service component.
The ConcreteAlgorithm class will be created by new in some places, then the collect method will be called.
I've read some related link like Spring #Autowired on a class new instance, and know that the above code cannot work, since the instance created by new has a #Resource annotated member.
I'm new to Spring/Java, and i wonder if there are some ways, or different design, to make scene like above work.
I've thought about use factory method, but it seems that it will involve many unchecked type assignment since i provided a generic interface.
UPDATE
To make it more clear, i add some detail about the problem.
I provide a RPC service for some consumers, with an interface like:
public interface TemplateRecommendService {
List<Long> recommendTemplate(TemplateRecommendDTO recommendDTO);
}
#Service
public class TemplateRecommandServiceImpl implements TemplateRecommendService {
#Override
public List<Long> recommendTemplate(TemplateRecommendDTO recommendDTO) {
TemplateRecommendContext context = TemplateRecommendContextFactory.getContext(recommendDTO.getBizType());
return context.process(recommendDTO);
}
}
As you can see, i will create different context by a user pass field, which represent different recommendation strategy. All the context should return List<Long>, but the pipeline inside context is totally different with each other.
Generally there are three main stage of the context process pipeline. Each stage's logic might be complicated and varied. So there exists another layer of strategy pattern.
public abstract class TemplateRecommendContextImpl<CollectOut, PredictOut> implements TemplateRecommendContext {
private CollectAlgorithm<CollectOut> collectAlgorithm;
private PredictAlgorithm<CollectOut, PredictOut> predictAlgorithm;
private PostProcessRule<PredictOut> postProcessRule;
protected List<CollectOut> collect(TemplateRecommendDTO recommendDTO){
return collectAlgorithm.collect(recommendDTO);
}
protected List<PredictOut> predict(TemplateRecommendDTO recommendDTO, List<CollectOut> predictIn){
return predictAlgorithm.predict(recommendDTO, predictIn);
}
protected List<Long> postProcess(TemplateRecommendDTO recommendDTO, List<PredictOut> postProcessIn){
return postProcessRule.postProcess(recommendDTO, postProcessIn);
}
public /*final*/ List<Long> process(TemplateRecommendDTO recommendDTO){
// pipeline:
// dataCollect -> CollectOut -> predict -> Precision -> postProcess -> Final
List<CollectOut> collectOuts = collect(recommendDTO);
List<PredictOut> predictOuts = predict(recommendDTO, collectOuts);
return postProcess(recommendDTO, predictOuts);
}
}
As for one specific RecommendContext, its creation likes below:
public class ConcreteContextImpl extends TemplateRecommendContextImpl<GenericTempDO, Long> {
// collectOut, predictOut
ConcreteContextImpl(){
super();
setCollectAlgorithm(new ShopDecorateCrowdCollect());
setPredictAlgorithm(new ShopDecorateCrowdPredict());
setPostProcessRule(new ShopDecorateCrowdPostProcess());
}
}
Instead od using field oriented autowiring use constructor oriented one - that will force the user, creating the implementation instance, to provide proper dependency during creation with new
#Service
public class ConcreteAlgorithm implements CollectAlgorithm<Integer> {
private QueryService queryService;
#Autowired // or #Inject, you cannot use #Resource on constructor
public ConcreteAlgorithm(QueryService queryService) {
this.queryService = queryService;
}
#Override
public List<Integer> collect() {
// dummy ...
return Lists.newArrayList();
}
}
There are 4 (+1 Bonus) possible approaches I can think of, depending on your "taste" and on your requirements.
1. Pass the service in the constructor.
When you create instances of your ConcreteAlgorithm class you provide the instance of the QueryService. Your ConcreteAlgorithm may need to extend a base class.
CollectAlgorithm<Integer> myalg = new ConcreteAlgorithm(queryService);
...
This works when the algorithm is a stateful object that needs to be created every time or, with some variations, when you actually don't know the algorithm at all as it comes from another library (in which case you might have a factory or, in rare cases which most likely don't fit your scenario, create the object through reflection).
2. Turn your algorithm into a #Component
Annotate your ConcreteAlgorithm with the #Component annotation and then reference it wherever you want. Spring will take care of injecting the service dependency when the bean is created.
#Component
public class ConcreteAlgorithm implements CollectAlgorithm<Integer> {
#Resource
QueryService queryService;
....
}
This is the standard and usually preferred way in Spring. It works when you know ahead of time what all the possible algorithms are and such algorithms are stateless.
This is the typical scenario. I don't know if it fits your needs but I would expect most people to be looking for this particular option.
Note that in the above scenario the recommendation is to use constructor-based injection. In other words, I would modify your implementation as follows:
#Component
public class ConcreteAlgorithm implements CollectAlgorithm<Integer> {
final QueryService queryService;
#Autowired
public ConcreteAlgorithm(QueryService queryService) {
this.queryService = queryService;
}
#Override
public List<Integer> collect() {
// dummy ...
return Lists.newArrayList();
}
}
On the most recent versions of Spring you can even omit the #Autowired annotation.
3. Implement and call a setter
Add a setter for the QueryService and call it as needed.
CollectAlgorithm<Integer> myalg = new ConcreteAlgorithm();
myalg.setQueryService(queryService);
...
This works in scenarios like those of (1), but lifts you from the need of passing parameters to the constructor, which "may" help getting rid of reflection in some cases.
I don't endorse this particular solution however as it forces to know that you have to call the setQueryService method prior to invoking other methods. Quite error-prone.
4. Pass the QueryService directly to your collect method.
Possibly the easiest solution.
public interface CollectAlgorithm<T> {
public List<T> collect(QueryService queryService);
}
public class ConcreteAlgorithm implements CollectAlgorithm<Integer> {
#Override
public List<Integer> collect(QueryService queryService) {
// dummy ...
return Lists.newArrayList();
}
}
This works well if you want your interface to be a functional one, to be used in collections.
Bonus: Spring's SCOPE_PROTOTYPE
Spring doesn't only allow to instantiate singleton beans but also prototype beans. This effectively means it will act as a factory for you.
I will leave this to an external example, at the following URL:
https://www.boraji.com/spring-prototype-scope-example-using-scope-annotation
This "can" be useful in specific scenarios but I don't feel comfortable recommending it straight away as it's significantly more cumbersome.
Related
I would like to create my own custom annotation. My framework is stand alone Java application. When someone annotate his pojo class a "hidden" code behind will trigger methods.
For example, today in Java EE we have #MessageDriven annotation.
And when you annotate your class with #MessageDriven and in addition implement MessageListener Interface there is a behind code that will trigger onMessage(Message msg). when a message arrives from a Queue/Topic.
How do I create an annotation (#MyMessageDriven) which could be added to a pojo and also implement MyCustomMessageListener.
The result which I desire is a trigger of "hidden" code (of mine) which will trigger a method of an implemented interface (exactly as it works with the sample i Wrote below).
I recommend to read this blog entry (snapshot on archive.org) up to the point where the author remembers (s)he has access to Spring's component scan feature.
The initial issue is to scan the class path to find classes with the custom annotation. Once this is done, you have the objects in your standalone application through which using object.getClass().getAnnotations(), you can then inject the listeners or custom behavior you need to add to the objects holding the custom annotations.
Let's say you have the following custom annotation:
#Target({ ElementType.TYPE })
#Retention(RetentionPolicy.RUNTIME)
public #interface MyMessageDriven {}
And you use it some class in you application:
#MyMessageDriven
public class MyObject {}
Now, in the appropriate location in your application, you should have a method to give out all classes carrying MyMessageDriven:
Set<Class<?>> findAllMessageDrivenClasses() {
final StopWatch sw = new StopWatch();
sw.start();
final Reflections reflections = new Reflections("org.projectx", new TypeAnnotationsScanner());
Set<Class<?>> allMessageDrivens = reflections.getTypesAnnotatedWith(MyMessageDriven.class); // NOTE HERE
sw.stop();
return allMessageDrivens;
}
Having this, I assume that there is a point in your application that either (1) you have access to the objects in your application, or (2) there is a visitor or iterator pattern on all the objects in the application. So, in some point, I assume that we have all targeted objects as objects:
Set<Class<?>> msgDrivenClasses = findAllMessageDrivenClasses();
for (Object o : objects) {
if (msgDrivenClasses.contains(o.getClass()) {
invokeTheMessageListener(o);
}
}
On the other hand, there should be some implementation of MyMessageListener that is available when the objects having MyMessageDriven are found:
void invokeTheMessageListener(Object o) {
theMessageListener.onMessage(o);
}
This answer is tailored from the blog entry so please refer to the blog for configuration of libraries. And, last but not least, this is a sample code for the problem and it can be refactored to more pattern-compatible and elegant style.
Update: There is a requirement that the targeted objects should be aware of their own listeners. So, I'd suggest the following approach. Let's have an interface MyMessageListenerAware:
interface MyMessageListenerAware {
MyMessageListener getMyMessageListener();
}
// and this is the original MyMessageListener
interface MyMessageListener {
void onMessage(Object o);
}
Now, the target objects should implement the above interface:
class MySampleObject implements MyMessageListenerAware {
public MyMesssageListener getMyMessageLisener() {
return mySampleObjectImplementationOfMyMessageListener;
}
}
Having this, the method invokeTheMessageListener becomes like:
void invokeMessageListener(Object o) {
if (o instance MyMessageListenerAware) {
MyMessageListener l = ((MyMessageListenerAware) o).getMyMessageListener();
l.onMessage(o);
}
}
Although, I strongly recommend reading about Visitor or Strategy pattern. What you aim to do seems to me like you need certain objects react/act/process to a common object/event in the application but each with their own interpretation/algorithm/implementation.
create an annotation something like this:
public #interface MyMessageDriven{
}
And you have an interface that can apply annotation like this:
public interface MyMessagListener {
public void message();
}
#MyMessageDriven
public class MyMessage implements MyMessagListener {
public void message(){
System.out.println(" I am executed")
}
}
Load the above class using classloader and using reflections check the annotation is presrent.
if it is present, use loaded instance to execute it.
Object obj = ClassLoader.getSystemClassLoader().loadClass("MyMessage").newInstance();
MyMessagListener mml = (MyMessagListener) obj;
mml.message();
Listener implementation you can put in MyMessage class or some other class that implements MessageListener.
In this case, need to provide implementation for message() what it is going to do.
But this class should be loaded and more important thing here is how your MyMessage class is loaded.
That is based on the meta data present in the MyMessage class.Similar way, in the real time scenario as well this is how it works.
Annotation is a metadata to a class that says based on the supplied data, do something.Had this metadata not present in the MyMessage class, you need not execute message() method.
Hope this will help you.
I would like to create an object that basically functions as a list, and i will inject it in my services, using Guice
public class MyRepository {
List<MyInterface> list = new ArrayList<>();
public void add(MyInterface obj){
list.add(obj);
}
public List<MyInterface> get(){
return list;
}
}
Then i am gonna to be using injection from various points to add elements to this list
public class ObjectA implements MyInterface {
#Inject
public ObjectA(MyRepository myRepository){
myRepository.add(this);
}
}
My question is, i want to ensure that MyRepository is used in services only after all potential subscribers have been added.
Multibinder is not applicable because i will be needed some specific methods
Is there a way to do that? Thanks
If you're using multibinder you're probably wanting to do something like this? You don't want to use static as it would break the #Inject MyRepository repository; logic downstream.
Assuming you have your multibinder configured appropriately then your repository should work like this:
class MyRepository {
Set<MyInterface> interfaces;
#Inject
public MyRepository(Set<MyInterface> interfaces) {
// Here you can do some things like re-applying the interfaces to
// a TreeSet (for example) if you needed to control priority.
this.interfaces = interfaces;
}
public Set<Permissions> getPermissions(final User user) {
// However you want to iterate through the interfaces
return interfaces.stream()
.flatMap(i -> i.getPermissions(user)) // maybe?
.collect(Collectors.toSet());
}
}
You can have:
Different methods for iterating the interfaces
You can filter the interfaces based on other Interfaces. For example if one MyInterface also extends MyOtherInterface
If I'm missing something, please update/comment and we can sort it out.
I have the following very simple interface:
public interface IDataSource<T> {
Observable<T> observable();
}
Now I'll be having multiple implementations of it. Each of those implementation may rely on varying parameters (different storage objects: JDBC, Cassandra, Redis...). So for instance I'll have:
public class CassandraDataSource implements IDataSource<MyCassandraObject> {
#Inject
public CassandraDataSource(Keyspace ks) {
// ...
}
}
public class OtherCassandraDataSource implements IDataSource<MyOtherCassandraObject> {
#Inject
public OtherCassandraDataSource(Keyspace ks) {
// ...
}
}
public class JDBCDataSource implements IDataSource<MyJdbcObject> {
#Inject
public JDBCDataSource(Database db) {
// ...
}
}
And so on.
What I would like is to reference each of those with a string so that i can call a factory which would return the appropriate IDataSource. Something that would behave like that:
public class DataSourceFactory {
public static final Map<String, Supplier<IDataSource<?>>> map = new HashMap<>();
#SuppressWarnings("unchecked")
public <T> IDataSource<T> get(String ref) {
return (IDataSource<T>) map.get(ref).get();
}
}
I could be giving N Providersas parameters (or direct field injection) to my factory (N being the number of IDataSource I use) and map strings to those in the constructor or use a switch in the get method but this would become quite a mess once I reach 10 to 20 IDataSource (or more!)
Is there some simpler solution I've been overlooking ?
Thanks
If you have to have a factory, then no—as in this question a manual factory is probably the best you can get.
However, if you bind all of your IDataSource implementations to IDataSource with different binding annotations, then you might be able to skip the factory and simply inject #Source("foo") IDataSource and get back the instance you want. The configuration between String and implementation still has to live somewhere, but you can have it live in a Guice module if you'd like. And, by injecting the Injector and supplying a compatible annotation implementation, you can even write a factory like DataSourceFactory that defers to Guice.
As a side note, beware of your DataSourceFactory; get will have no safe way to supply a value for its type parameter T.
I'm trying to set up a Provider for DAOs created using JDBI. JDBI uses a Handle object (which is a wrapper around a JDBC Connection) and you can get hold of a DAO by using handle.attach(MyDaoType.class). Rather than having to write a separate Provider implementation for every DAO class I thought it would make sense to do this:
public class DaoProvider<T> implements Provider<T> {
private final Class<T> daoType;
private final Handle handle;
#Injected
public DaoProvider(Class<T> daoType, Handle handle) {
this.daoType = daoType;
this.handle = handle;
}
#Override
public T get() {
return handle.attach(daoType);
}
}
But it seems tremendously difficult to wire this up with Guice. I have tried using the #Assisted annotation on the 1st constructor argument as suggested in this answer. I defined a factory like this:
public interface DAOProviderFactory {
<T> DAOProvider<T> create(Class<T> daoType);
}
But it's not clear how I should invoke the FactoryModuleBuilder.implemented method as the whole point is that I don't want to have to extend my provider class.
It also seems a bit crazy that I'd have a factory that returns a provider that returns the thing I actually want!
It strikes me that this would be really easy to do with the Spring DI container so I want to believe it's possible with Guice. Can anyone point me in the right direction?
Thanks to #condit for pointing me at something that enabled me to solve the issue. It's actually very simple. I changed the Provider implementation to use field injection for the Handler like this:
public class DAOProvider<T> implements Provider<T> {
private #Inject Handle handle;
private final Class<T> daoType;
public DAOProvider(Class<T> daoType) {
this.daoType = daoType;
}
#Override public T get() {
return handle.attach(daoType);
}
}
Then in any module or application where I have specific DAO classes I want to bind I can just do something like this:
bind(UserStore.class).toProvider(new DAOProvider<>(UserStore.class));
bind(MessageStore.class).toProvider(new DAOProvider<>(MessageStore.class));
Guice then injects the Handle into the DAOProvider instances automatically.
I think you're making this far too complicated. When you call the get() method, you are storing the result in a reference, which means you know the type of the particular DAO, which means you can write your code knowing the DAO class. I mean, think about how Guice itself works, you call Injector.getInstance(Class<?> type)... in other words, methods like this can't infer the type without you passing the Class anyway, so pass the Class when you use it!
I can understand why you might not want to inject Handle directly though, so why not just make a wrapper, e.g.
public interface DaoProvider {
<T> T provideDao(Class<T> daoType);
}
And then:
public class JdbiDaoProvider implements DaoProvider {
private final Handle handle;
#Inject
JdbiDaoProvider(Handle handle) {
this.handle = handle;
}
public <T> T provideDao(Class<T> daoType) {
return handle.attach(daoType);
}
}
I'm using Hibernate. The question is at the bottom.
The current strategy
It's simple.
First of all, I have a basic Dao<T>.
public class Dao<T> {
private Class<T> persistentClass;
private Session session;
public Dao(Class<T> persistentClass) {
this.persistenClass = persistentClass;
this.session = HibernateUtil.getCurrentSession();
}
It's nice as a base class and it passes the most common methods up to its Session.
public T get(Serializable id) {
#SuppressWarnings("unchecked")
T t = (T) this.session.get(this.persistentClass, id);
return t;
}
protected Criteria getCriteria() {
return this.session.createCriteria(this.persistentClass);
}
When there's need to use queries on the model, it goes into a specific DAO for that piece of model, which inherits from Dao<T>.
public class DaoTask extends Dao<Task> {
public DaoTask() {
super(Task.class);
}
public List<Task> searchActiveTasks() {
#SuppressWarnings("unchecked")
List<Task> list = (List<Task>) this.getCriteria()
.add(Restrictions.eq("active", true))
.list();
return list;
}
}
This approach has always worked well.
However...
However, today I found that many times an instance needs reattachment to the Session and a line similar to the following ends up happening:
new Dao<Book>(Book.class).update(book);
... which I find to be bad, because
I don't like specifying the redundant Book.class
If ever a DaoBook arises, this construct will become obsolete.
So I turned Dao<T> into an abstract class, and went on to refactor the old code.
Question
In order to remove the Dao<T> references from the codebase, I thought of two approaches:
Create specific DAOs for every class that ever needs attachment, which would generate many almost empty DaoBooks and the sort.
Create a class that owns a Dao<Object> and exposes only the attachment methods (i.e. save(), update() etc).
I'm tending to go with #2, but I thought this "AttacherDao" pattern might be bad, so I'd like your opinion.
Any cons for #2? Also, do you find anything wrong with "the current strategy"?
Our approach is to have a DAO object (derived from a commonDao) for each persistent class. In fact we define interface for this DAO class and each DAO decides which interfaces are opened up.
Using the following code, user cannot delete the PersistentClass.
interface PersistentClassDao {
void save(PersistentClass persistentObject);
}
Class PersistentClassDaoImpl extends CommonDao implements PersistentClassDao {
void save(persistentObject) {
persist(persistentObject);
}
Even though it has some additional overhead, this approach helps in unit testing appropriate code before exposing an interface.
We've chosen an approach similar to lud0h's, with the following twist:
abstract class<T extends IModelObject> JdbcCrudDao<T>{
void create(T dbo){}
T findByFoo(String foo){}
void update(T dbo){}
void delete(T dbo){}
}
class BarDao extends JdbcCrudDao<Bar>{
}
But, the twist is that we selectively expose methods on the Dao through a facade and forward only those we absolutely must.
class BarController implements IController{
private static final BarDao dao;
// ...
void update( IBar bar ){
dao.update(bar);
}
}
The only short-coming in all this is it requires some casting about if you wish to hide your database keys behind an interface type (which we do), but it's a pretty minor inconvenience versus the alternative (database code outside of the Daos).
Couple of questions
Are you frequently creating your DAO to do a single task or are these long lived?
What about using a static function? Clearly your Book object can be bind the DAO function to without the Book.class reference...
Otherwise, I'm a little worried about keeping the session object around instead of fetching whatever the current session is - isn't it considered "bad" to have long lived session objects? I'm not a master of DAO, so maybe I'm missing something here.