1

I have a Spring 3 project which acts as a Rest API, and wanted to wire a spring bean I have into an unmanaged class for logging purposes.

After trying many different things, what worked was marking my unmanaged class with the annotation @Configurable.

Like:

@Configurable
public class ClassNotManagedBySpring {
     @Autowired
     @Qualifier("myBean")
     private MyBean myBean;
}

@Service("myBean")
public class MyBean {
     @Autowired
     @Qualifier("someOtherBean")
     private SomeOtherBean someOtherBean;
}

And then in my beans.xml:

<context:spring-configured/>

So now let's say that ClassNotManagedBySpring.java, is one of 6 classes that all do something similar, except 3 of them ARE managed by spring because they have the @Component annotation.

But all 6 of these classes need to @Autowire MyBean.java and only some need the @Configurable annotation.

To note, I was already previously using AspectJ in this app for multiple other purposes.

I want to know what is the risk in my spring application by all of a sudden wiring spring managed dependencies into un managed classes in this way?

Can there be performance issues? Risks of errors at runtime?

If this isn't the best way of wiring a spring managed bean into an unmanaged class, what is?

Adam Bronfin
  • 1,209
  • 3
  • 27
  • 43

1 Answers1

1

I've been using @Configurable for years without issues, it's a very easy solution if you need app instantiated beans configured by Spring. My use cases were all in the UI tier. I also used @Configurable(preConstruction = true) whenever I needed autowired values already in the constructor. Of course, if you make millions of @Configurable objects it might be a performance issue, otherwise I wouldn't worry too much about it. The only small aesthetic problem I had was Eclipse giving me some red underlines at class definitions extending @Configurable classes, complaining that the hierarchy of class SomeClass is inconsistent, but it compiled them nevertheless, no errors in the Problems view or at runtime whatsoever.

Nándor Előd Fekete
  • 6,988
  • 1
  • 22
  • 47
  • What if I want to use the same spring bean in classes not managed by spring in addition to beans that are set up in the container? – Adam Bronfin Apr 03 '16 at 11:13
  • That's the whole purpose to using `@Configurable`. – Nándor Előd Fekete Apr 03 '16 at 11:59
  • Hmm, well since doing it now, the classes I have annotated as configured auto wire my dependency fine, and the classes are annotated like: @Configurable(autowire=Autowire.BY_TYPE, preConstruction = true), but now in my other classes that dont have Configurable and are managed by spring as beans, I get the following: – Adam Bronfin Apr 03 '16 at 18:07
  • nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)': Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public static java.lang.Object org.apache.cxf.configuration.jsse.spring.TLSClientParametersConfig.createTLSClientParameters(java.lang.String)] threw exception; nested exception is java.lang.RuntimeException: java.io.FileNotFoundException: – Adam Bronfin Apr 03 '16 at 18:07
  • I think that error is related to your specific configuration, not something related to using `@Configurable` in general. – Nándor Előd Fekete Apr 03 '16 at 18:47
  • What could be causing it now that I'm using Configurable though? This wasn't happening before, worries me that there are sychronization issues with the "myBean" object I'm trying to use in other places. – Adam Bronfin Apr 03 '16 at 19:22
  • Is it a good solution to instead create a wrapper object for MyBean.java, which is annotated with Configurable, so then that way whenever I need "myBean", I just call new MyBeanHolder().getMyBean()? – Adam Bronfin Apr 03 '16 at 19:23
  • There's no need to introduce wrapper objects to get references to spring managed beans, that would defeat the purpose of `@Configurable`. Regarding concurrency issues: if you're using spring beans of the default scope of `singleton`, your beans should be stateless, so no synchronization should be needed. But that's not specific to `@Configurable` either - your `singleton` beans should be stateless even if you're not using `@Configurable`. Just create an exception type breakpoint for `FileNotFoundException` and see what's causing the error. – Nándor Előd Fekete Apr 03 '16 at 19:39
  • Since I have added to my beans.xml, is it possible this line is causing configuration issues for other beans? What's happening is that very strangely a field on another bean being used within that class is failing to autowire in a very strange way, and this wasn't occurring before. – Adam Bronfin Apr 03 '16 at 19:42
  • The class it's failing on is a SOAP service client generated from a WSDL, and it's annotated with WebService. – Adam Bronfin Apr 03 '16 at 19:46
  • I think it's close to impossible to tell what is the problem with your configuration without a [mcve]. `@Configurable` in itself shouldn't be a problem as I was using it for years and never had any problem. This error you're getting is specific to your configuration and it's hard to tell what can be the cause without a sample project which reproduces it. I guess you have two choices now. Either try to make a sample project which reproduces the problem and share it on github or debug it yourself. – Nándor Előd Fekete Apr 03 '16 at 20:45
  • Ok, I do think I know what that issue is about. But what would you recommend for options in my case to pass to Configurable? You mentioned preConstruction=true, what would you recommend in my case? autowire=Autowire.BY_TYPE, etc? – Adam Bronfin Apr 03 '16 at 21:07
  • You only need to specify the `autowire` attribute if you want autowiring to occur automatically, without you explicitly specifying `@Autowired` annotations on fields or configuration methods (_usually_ setters). I prefer to indicate my autowired fields/method explicitely, so I leave that attribute to the default (Autowire.NO). `preConstruction = true` is only needed in case you need the autowired fields/properties in the call graph of your constructor, otherwise I would leave it as the default value of `false`. – Nándor Előd Fekete Apr 03 '16 at 22:38
  • You seem to annotate your to-be-autowired fields with `@Autowired` in your `@Configurable` class `ClassNotManagedBySpring` so the `autowire=Autowire.BY_TYPE` attribute is not needed. – Nándor Előd Fekete Apr 03 '16 at 22:42
  • I see. What would happen if I marked as @Configurable a class that was already managed by spring as a bean? – Adam Bronfin Apr 04 '16 at 00:19
  • I never tried to do that, so I can only speculate. As soon as the bean gets instantiated by Spring, the `AnnotationBeanConfigurerAspect` will kick in and do the bean configuration via Spring. It might fail right away, if the Spring context is not initialized yet. In case it succeeds, Spring will probably consider it just as any other object it just instantiated and will proceed with configuring the bean again. If the bean doesn't have any mechanism that would prevent it being configured twice, it would probably succeed with the second configuration and the story is over. – Nándor Előd Fekete Apr 04 '16 at 00:54