I am trying to implement a generic abstract class in my service layer. I am already using a simliar pattern in my dao layer and it works fine. I found a working example in the Spring in Practice v8 ebook. I am wondering if there is a way to autowire the following working code. (The code works but I have to call my helper method 'setDao' before I use any other method in the class)
Test class:
public class App {
public static void main(String[] args) {
ApplicationContext appContext = new ClassPathXmlApplicationContext("classpath:/applicationContext.xml");
MyService service = (MyService)appContext.getBean("myService");
service.setDao();
Heading detail = new Heading();
detail.setName("hello");
service.save(detail);
Heading dos = service.findById(Long.valueOf(1));
System.out.println(dos);
}
}
MyServiceImpl class
#Service("myService")
public class MyServiceImpl extends AbstractServiceImpl<Heading> implements HeadingService {
#Autowired
private HeadingDao headingDao;
public void setHeadingDao(HeadingDao headingDao) {
this.headingDao = headingDao;
}
public void setDao() {
super.setDao(this.headingDao);
}
}
MyService interface
public interface HeadingService extends AbstractService<Heading> {
public void setDao();
}
AbstractServiceImpl class
#Service
public abstract class AbstractServiceImpl<T extends Object> implements AbstractService<T> {
private AbstractDao<T> dao;
public void setDao(AbstractDao<T> dao) {
this.dao = dao;
}
public void save(T t) {
dao.save(t);
}
public T findById(Long id) {
return (T)dao.findById(id);
}
public List<T> findAll() {
return dao.findAll();
}
public void update(T t) {
dao.update(t);
}
public void delete(T t) {
dao.delete(t);
}
public long count() {
return dao.count();
}
}
AbstractService interface
public interface AbstractService<T extends Object> {
public void save(T t);
public T findById(Long id);
public List<T> findAll();
public void update(T t);
public void delete(T t);
public long count();
}
Instead of having to call a method (setDao()) to allow your subclass to pass the DAO reference to your superclass, why reverse the direction and force the subclass to supply the DAO to the superclass?
for example:
public abstract class AbstractServiceImpl<T extends Object> implements AbstractService<T> {
private AbstractDao<T> dao;
abstract AbstractDao<T> getDao();
public void save(T t) {
getDao().save(t);
}
}
public class FooServiceImpl extends AbstractServiceImpl<Foo> {
#Autowired
private FooDao fooDao;
#Overrides
public AbstractDao<Foo> getDao() {
return fooDao;
}
}
There is no need to call a method externally to kick the reference-passing-chain into action.
Try making your MyServiceImpl implement InitializingBean, and change your setDao() method to be afterPropertiesSet(). It will automatically get called after the framework is done calling setters.
Or, (even more simple), just call setDao() in your setHeaderDao(...) method.
Upgrade spring framework version to 4, and the problem will be solved.
check this page.
Related
My service has a #Controller with multiple APIs.
Each API accepts a specific kind of object.
I would like to inject a single interface into a controller class, but have different implementations of the interface depending on the type of the input argument - is that possible?
#Controller
public class ApiClass{
private final Service service;
public ApiClass(Service service) {
this.service = service;
}
public ResponseEntity<Response> apiFirst (Object1 object1) {
return ResponseEntity.ok(service.process(object1));
}
public ResponseEntity<Response> apiTwo (Object2 object2) {
return ResponseEntity.ok(service.process(object2));
}
}
public interface Service <T extends OwnObjectClass>{
void process (T object);
}
public class Implementation1 implements Service {
#Override
void process (Object1 object) {
--some code;
}
}
public class Implementation2 implements Service {
#Override
void process (Object2 object) {
--some code;
}
}
How to do it correctly so that for each implementation not to add a new injection to the ApiClass?
Spring will provide the primary bean for the interface implementation unless you use the #Qualifer annotation with the desired instance. The injected bean can not mutate to another instance.
If you don't want to use multiple injections in the controller, you can create a ServiceProvider and ask for a specific implementation each time.
Here is an example:
public class ApiClass{
private final ServiceProvider provider;
public ApiClass(ServiceProvider provider) {
this.provider = provider;
}
public ResponseEntity<Response> apiFirst (Object1 object1) {
return ResponseEntity.ok(provider.getService("Implementation1").process(object1));
}
public ResponseEntity<Response> apiTwo (Object2 object2) {
return ResponseEntity.ok(provider.getService("Implementation2").process(object1));
}
}
#org.springframework.stereotype.Service
public class ServiceProvider {
private Map<String, Service> services;
public ServiceProvider(List<Service> services) {
this.services = services.stream()
.collect(java.util.stream.Collectors.toMap(
Service::type,
service -> service
)
);
}
public Service getService(String type) {
return services.get(type);
}
}
interface Service<T extends OwnObjectClass> {
String type();
void process(T object);
}
#org.springframework.stereotype.Service("Implementation1")
class Implementation1 implements Service {
#Override
public String type() {
return "Implementation1";
}
#Override
public void process(OwnObjectClass object) {
}
}
#org.springframework.stereotype.Service("Implementation2")
class Implementation2 implements Service {
#Override
public String type() {
return "Implementation2";
}
#Override
public void process(OwnObjectClass object) {
}
}
You can change the string in the type for an Enum.
There is another way using HandlerMethodArgumentResolver where you can inject your dependency directly into the method definition.
Here is a nice article explaining it: https://reflectoring.io/spring-boot-argumentresolver/
So I want to achieve something like this:
#Component
public class ComponentA {
public void doThis(){};
}
#Component
public class ComponentB {
public void doThat(){};
}
public interface MyInterface {
void doSomething();
}
public class MyInterfaceImplA implements MyInterface {
private final ComponentA componentA;
#Inject
public MyInterfaceImplA(ComponentA componentA){
this.componentA = componentA;
}
public void doSomething(){
componentA.doThis();
}
}
public class MyInterfaceImplB implements MyInterface {
private final ComponentB componentB;
#Inject
public MyInterfaceImplB(ComponentB componentB) {
this.componentB = componentB;
}
public void doSomething() {
componentB.doThat();
}
}
What I basically want is to inject different components into different classes implementing the same interface.
My question is if there is a good way to set this architecture up in this or a similar way? Or is there a pattern to achieve this in a better way?
I have my AbstractBinder and I bind several classes with the same interface. Let's say I bind Fish and Cat which both implement Animal interface.
What is the easiest/proper way of injecting them into a bean which takes Collection<Animal> ?
PS: Spring has equivalent in simply #Autowire List<Animal> and the collection is created and populated by Spring.
HK2 has IterableProvider<T>, as mentioned here in the documentation. You can get the service by name, by qualifier annotation, or just iterate over them, as it's an Iterable. Just for fun, here is a test.
public class IterableProviderTest {
public static interface Service {}
public static class ServiceOne implements Service {}
#QualAnno
public static class ServiceTwo implements Service {}
#Qualifier
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public static #interface QualAnno {
public static class Instance
extends AnnotationLiteral<QualAnno> implements QualAnno {
public static QualAnno get() {
return new Instance();
}
}
}
public class Binder extends AbstractBinder {
#Override
protected void configure() {
bind(ServiceOne.class).to(Service.class).named("one");
bind(ServiceTwo.class).to(Service.class).qualifiedBy(QualAnno.Instance.get());
}
}
#Inject
private IterableProvider<Service> services;
#Test
public void test_IterableProvider() {
ServiceLocator locator = ServiceLocatorUtilities.bind(new Binder());
locator.inject(IterableProviderTest.this);
assertEquals(2, services.getSize());
Service serviceOne = services.named("one").get();
assertTrue(serviceOne instanceof ServiceOne);
Service serviceTwo = services.qualifiedWith(QualAnno.Instance.get()).get();
assertTrue(serviceTwo instanceof ServiceTwo);
}
}
UPDATE
For a List<Service> (to avoid HK2 InterablProvider), the only think I can think of is to use a Factory and inject the IterableProvider into it, and from there return the list. For example
public class Binder extends AbstractBinder {
#Override
protected void configure() {
...
bindFactory(ListServiceFactory.class).to(new TypeLiteral<List<Service>>(){});
}
}
public static class ListServiceFactory implements Factory<List<Service>> {
#Inject
private IterableProvider<Service> services;
#Override
public List<Service> provide() {
return Lists.newArrayList(services);
}
#Override
public void dispose(List<Service> t) {}
}
Yeah it's a little bit of extra work.
In the latest release of hk2 (2.4.0) you can
#Inject Iterable<Foo> foos;
That allows you to keep your pojo's without any hk2 API in them.
For more information see: Iterable Injection
In MyInterceptor, which interface, Ifclocal or IfcRemote, invoked the method doStuff in MyEjb? It's possible know through which "channel" your bean was called?
I need know which dependency injection invoked the method.
#Local
public interface IfcLocal {
void doStuff(String s);
}
#Remote
public interface IfcRemote {
void doStuff(String s);
}
#Stateless
#Interceptors({ MyInterceptor.class })
public class MyEjb implements IfcLocal, IfcRemote {
#Override
public void doStuff(String s) {
System.out.println(s);
}
}
public class MyManagedBean {
#EJB private ifcLocal ifcLocal;
#EJB private IfcRemote ifcRemote;
public void go() {
ifcLocal.doStuff("xxx");
ifcRemote.doStuff("xxx");
}
}
public class MyInterceptor {
#AroundInvoke
public Object intercept(InvocationContext inv) throws Exception {
// ??? who invoked ???
System.out.prinln(inv.getTarget().getClass()); // print MyEjb
}
}
Inject #Resource private SessionContext sessionContext; in MyInterceptor. After: Class<?> interfaceReference = sessionContext.getInvokedBusinessInterface().
I am trying to determine if generics would be able to help me with designing a better and scalable solution. In my application, there is a model class which is responsible for loading data from data sources and I use a ModelProxy class to expose some of the methods in the Model class.
public interface ModelProxy {
public int getOrderCount();
public int getCustomerCount();
}
public abstract class AbstractModel {
public abstract ModelProxy loadData(Configuration configuration);
}
public class ConcreteModel extends AbstractModel {
public ModelProxy loadData(Configuration configuration) {
loadInternal();
return new ConcereteModelProxy(this);
}
}
Everything looks good so far, but I am looking to see if generics (with wildcards) can help me design a better solution that would allow to be extend the ModelProxy interface or the Configuration class. For example, in another Concrete Model class I woukd like to use a ExtendedConfiguration class and ExtendedModelProxy.
public ExtendedModelProxy extends ModelProxy {
// Additional methods
public int getTotalCount();
}
public class ConcereteModel2 extends AbstractModel {
public ExtendedModelProxy loadDate(ExtendedConfiguration configuration) {
return new ConcreteExtendedModelProxy(this);
}
}
Will Java Generics help me to achieve something like above?
Or Maybe my design is flawed that I need to re-design it. Any suggestions would be very helpful.
Thanks,
Example Client Code:
public abstract class Service {
public ModelProxy load(Configuration configuration) {
return getModel().loadData(configuration);
}
protected abstract AbstractModel getModel();
}
public class ServiceImpl extends Service {
protected AbstractModel getModel() {
return new ConcreteModel();
}
public static void main() {
Service service = new ServiceImpl();
ModelProxy proxy = service.load(configuration);
System.out.println(proxy.getOrderCount());
}
}
public class ExtendedServiceImpl extends Service {
protected AbstractModel getModel() {
return new ConcreteModel2();
}
public static void main() {
Service service = new ExtendedServiceImpl();
ExtendedModelProxy proxy = (ExtendedModelProxy) service.load(configuration);
System.out.println(proxy.getTotalCount());
}
}
I hope to not have confused with too much. In the ExtendedServiceImpl, you can see I need to cast ModelProxy to ExtendedModelProxy to be able to access the method getTotalCount. My thinking was maybe I can use generics to avoid the casts. Something like
public abstract <M extends ModelProxy, C extends Configuration> M loadData(C configuration);
Maybe I am overcomplicating things and really my current design is all I need. Not sure...
How about this kind of thing
package jj;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.*;
interface Configuration {
}
interface Model {
}
interface OrderModel extends Model {
public int getOrderCount();
public int getCustomerCount();
}
interface CustomerModel extends Model {
public int getName();
public int getAddress();
}
abstract class AbstractModel<M extends Model> {
#SuppressWarnings("unchecked")
public M loadData(Configuration configuration) {
// connect to stuff
Object connection = null;
loadInternal(configuration, connection);
// do some other stuff
return (M) Proxy.newProxyInstance(null, new Class<?>[]{getModelClass()}, null);
}
protected abstract void loadInternal(Configuration configuration,
Object connection);
protected abstract InvocationHandler getInvocationHandler(Object connection);
protected abstract Class<M> getModelClass();
}
class ConcreteOrderModel extends AbstractModel<OrderModel> {
public void loadInternal(Configuration configuration,
Object connection) {
}
protected InvocationHandler getInvocationHandler(Object connection) {
return null;
}
protected Class<OrderModel> getModelClass() {
return OrderModel.class;
}
}
class ConcreteCustomerModel extends AbstractModel<CustomerModel> {
public void loadInternal(Configuration configuration,
Object connection) {
}
protected InvocationHandler getInvocationHandler(Object connection) {
return null;
}
protected Class<CustomerModel> getModelClass() {
return CustomerModel.class;
}
}