简体   繁体   中英

Tapestry 5 and Spring beans with same interface

I have a problem with Tapestry 5 and Spring integration. Problem occurs if I have a multiple beans that implement the same interface and I try to inject them with @Inject annotation. Of course I got an exception.

I found a tutorial that says that in that case I have to use @Service annotation too but now I'm getting

org.apache.tapestry5.internal.services.TransformationException
Error obtaining injected value for field 
com.foo.pages.Foo.testService: Service 
id 'someServiceIDeclaredInSpringContextFile' is not defined by any module...

Anyway, question is: How can I inject two different spring beans, that implement a same interface, into Tapestry 5 page?

I solved this problem.

First I made a new annotation

public @interface Bean {
    String value();
}

and I use this wherever I have this one of multiple beans implementing same interface

@Inject
@Bean("springBeanName")
Service foo;

Then I changed org.apache.tapestry5.internal.spring.SpringModuleDef

private ContributionDef createContributionToMasterObjectProvider() {
  ....
  public void contribute(ModuleBuilderSource moduleSource, 
                ServiceResources resources,
                OrderedConfiguration configuration) {
    ....
    switch (beanMap.size()) {
           case 0:
             return null;
           case 1:
             Object bean = beanMap.values().iterator().next();
             return objectType.cast(bean);
           default:
             Bean annotation = annotationProvider.getAnnotation(Bean.class);
             Object springBean = null;
             String beanName = null;

             if (annotation != null) {
               beanName = annotation.value();
               springBean = beanMap.get(beanName);
             } else {
               String message = String.format(
                 "Spring context contains %d beans assignable to type %s: %s.",
                 beanMap.size(),
                 ClassFabUtils.toJavaClassName(objectType),
                 InternalUtils.joinSorted(beanMap.keySet()));
               throw new IllegalArgumentException(message);
             }
             if (springBean != null) {
               return objectType.cast(springBean);
             } else {
               String message = String.format(
                 "Bean [%s] of type %s doesn't exists. Available beans: %s",
                 beanName, ClassFabUtils.toJavaClassName(objectType),
                 InternalUtils.joinSorted(beanMap.keySet()));
               throw new IllegalArgumentException(message);
             }
           }
         }
       };

It sounds like you either have a typo in the name give to the @Service annotation, or you have not actually defined the bean with the name that you are expecting. Without more information, it is hard to tell for sure, as there are also some other possibilities.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM