In my main() method I create a PersonCollection Object using Spring and then I start to load different Persons objects.
BeanFactory appContext = new ClassPathXmlApplicationContext("cp-beans.xml");
PersonCollection pc = appContext.getBean(PersonCollection.class);
Person aPerson = pc.loadById(1);
aPerson.doSomething();
aPerson.loadById(1067);
aPerson.doSomething();
In turn PersonCollection.loadById() can load the object from memcached or from Amazon SimpleDB:
public Person loadById(int id) throws ConnectException, NoSuchElementException {
String memCacheKey = "Person-" + id;
Person aPerson = (Person) cache.get(memCacheKey);
if (aPerson != null) {
return aPerson; //cache hit
}
aPerson = loadByIdFromSdb(id); //cache miss, read it from SimpleDB
cache.set(memCacheKey, aPerson);
return aPerson;
}
So there are two ways to create a Person, the first is deserializing from memcached, the second will call new Person() and assign all data.
Person has two #Autowired properties and is declared as a #Service and the package is in context:component-scan, however the dependencies are not passed, because the bean is created with new or from the cache and not with the Spring framework.
I could use appContext.getBean() to create the Person Object, however, it would mean to pass around the applicationContext and use getBean() inside the application, which doesn't feel right.
How to solve the problem?
UPDATE: I read the documentation and tried the suggestion of Ryan Stewart and wrote a small example project to try it. It works great, thank you!
https://github.com/stivlo/spring-di
Ultimately, I've refactored my original project, in a way that I don't need this feature anymore, but is a good tool to have in my arsenal.
Yes, avoid ApplicationContext.getBean() in your (non-infrastructure) code like the plague.
Option one: Don't autowire your POJO-like classes. Pull that out into a "service" object that is tightly coupled to the Person. This is more or less the current mainstream approach, and I hope it goes away because it gets messy.
Option two: Use AspectJ weaving with the #Configurable annotation to make Person autowirable regardless of where it's instantiated. I really like this option, though I haven't used it in a production project yet.
You may also want to look into a little oddball utility class called ObjectFactoryCreatingFactoryBean, which is a way of "reusing" the capabilities of the BeanFactory without unduly contaminating your business code with worrying about bean names.
<beans>
<bean id="PersonCollection " class="com.example.PersonCollection">
<property name="personMaker" ref="PersonMaker"/>
</bean>
<bean id="personPrototype" class="com.example.Person" scope="prototype">
<!-- Things to inject onto a newly-made person -->
</bean>
<bean id="PersonMaker" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
<property name="targetBeanName"><idref local="personPrototype"/></property>
</bean>
</beans>
In this way, your PersonCollection instance doesn't need to know any bean names, but can get a fresh Person (with the specified dependencies injected) via:
Person p = (Person) this.personMaker.getObject();
IMO there are some ways it could be made much more convenient (such as working with an inner bean rather than idref) but that would require some Spring-guru and a custom XML namespace.
Related
here the situation:
i got some beans (called Systems). These beans work with external system to gather data and do more (like analyze them, or store them in database etc.). These systems also got some beans to do the work (the work called before, gather / read, analyze, store, etc).
I got a spring context xml where these beans (systems) are defined like:
<bean id="SomeSystem" class"..."/>
All these systems have the same Interface...let's call it "MommyInterfaceSystem"...
And i got also a simple util:list config, like this:
<util:list id="MyAwesomeSystemsList">
<ref bean="SomeSystem"/>
<ref bean="AnotherSystem"/>
...
</util:list>
As you can see i got some "Systems" like "SomeSystem" and "AnotherSystem" - both implementing "MommyInterfaceSystem"...whatever...
These systems are get called over another Class. Let's call it "GatherInformationFromSystems".
This class has this structure:
public class GatherInformationFormSystems {
#Resource(name "MyAwesomeSystemsList")
private final List<MommyInterfaceSystem> informationSystems = new ArrayList<MommyInterfaceSystem>();
public void execute() {
...
for(MommyInterfaceSystem s : informationSystems) {
...
s.gatherInformation();
...
}
...
}
}
And now i want to test the results of this process! And here we arrive the my problem.
I wrote a simple unit test to execute the process of gathering information. This process works and it is fine.
I wrote many test for this process and it works greats but if i want to mock an external system (because i want to predefine the return value) it fails...
If i call the gather bean directly (not over the util:list...it works...but then the other actions like analyze or store won't get called...).
I have to do something like this:
If AnotherSystem of informationSystems is calling the "gatherInformation" method of - it is gonna call another method (let's call it "doCall").
And i want to mock this method. The method doCall.
All should be the same, except this method (doCall). Here i want to return a predefined Object.
Sry for this bad explanation, my english is damn bad...but i hope you will understand my problem :/
here i can list what i tried...
i tried to get the system from the list with reflections and replaced it with a mock...the result is a nullpointer exception because of missing autowired beans...
I autowired the bean directly and tried to mock it:
Mockito.when(anotherSystem.doCall(Mockito.anyString()).thenReturn(data);
I tried to create the object with EasyMock.mock...also failed
I didn't try to create a xml context to override the bean definition with own bean, because the system contains many other method which get called...and...yeah...pity...
The Question
I'm new to Java and spring and I'd like to know how to structure code which marshals different objects from XML and then processes them. I'm converting some code JAVA code from before my time to use spring. I know the way I've approached this this probably, wrong but If someone could offer a few pointers on how to restructure things "the Spring way" that would help alot. I've read a lot of the Spring docs, but I'm finding it hard to apply what is in there to my code.
The Situation
I'm not going to post the whole code tree as even and simple example is a lot of code (which is the problem). So I'll just describe the method.
I've got XML and schemas for two classes CLASSA & CLASSB. I've generated JAVA wrappers using xjc. I've got a JAVA class which is a wrapper for the JAXB marshaller. The wrapper needs to be given the class name and the package name of the class to be marshalled on construction.
public JaxbWrapper(String ClassName, String packageName) throws ClassNotFoundException, InstantiationException,
IllegalAccessException, JAXBException
{
this.packageName = packageName;
// set the context is the expensive operation
setJAXBContext(Class.forName(fullJaxbClassName(ClassName)).newInstance());
// get the schma from preset schema dir
schemaFileName = findSchema(ClassName);
myMarsheller = jc.createMarshaller();
myMarsheller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
}
I've then got one bean for each instance of the JaxBWrapper for both ClassA and ClassB. They are almost identical so only the one for class A is shown.
<bean id="jaxbParser_CLASSA" class="org.test.JAXB.JaxbWrapper"
lazy-init="true" scope="prototype">
<constructor-arg index="0" type="java.lang.String"
value="CLASSA" />
<constructor-arg index="1" type="java.lang.String"
ref="testPackage" />
<property name="encoding" ref="xmlEncoding" />
</bean>
Unhelpfully the XML files I have to process are delivered one at a time in file with a fixed name and a rolling counter (and I cannot change that). So I'm unable to tell what object is in the file from the filename. I've have a tiny utility function which check which the object type is in the file I'm trying to process.
I then have the following function:
public static Object loadXML(String xmlFile, String fileName) throws Exception
{
InputStream iStream = XmlUtils.openFile(xmlFile);
String xmlObjectType = XmlUtils.getObjectTypeFromXML(xmlFile);
// get the right JAXB processor
JaxbWrapper jaxB = myContext.getBean("jaxbParser_" + xmlObjectType , JaxbWrapper.class);
Object obj = jaxB.objectFromXML(iStream, xmlObjectType , fileName);
return obj;
}
So I'm taking the object name and getting the right bean from the context. This means I could use things like Spring's object pool to hold lots of JaxbWrappers for different objects. However the way I've implemented this feels wrong to me. I don't like the myContext.getBean("jaxbParser_" + xmlObjectType method of getting the JaxbWrapper bean.
So my question is: Is there a better way of structuring this code? A few simple pointers would be very much appreciated.
Additional Complexity
This is where things, at the moment, become really unmanageable. Once the marshaling stage has completed I've got a post processing stage where there are several different post processor for each class type. I've got Spring beans for each of these and I'm getting them from the application context using:
myContext.getBean(xmlObjectType + "_" + processorType + "_" + xmlObjectType);
where:
xmlObjectType is a string CLASSA or CLASSB which is set by reading the object type from the file (as above).
processorType is s string which is set from the comand line.
To set the proceesorType I'm doing something like the following when the application starts.
if (line.hasOption("file"))
{
processorType = "FileProcessor";
}
if (line.hasOption("print"))
{
processorType = "PrintProcessor";
}
Again, I don't think this is the right way to do things, but It's the best I've got at the moment :-(.
I guess the more general question is how do JAXB and Spring work together? In the real world I have lots very large and complex CLASSA and CLASSBs. I've got java classes for these generated by xjc. As I'm using xjc I have to use jaxb (I guess). The question is how to do that in the Spring world.
Or can I get rid of JAXB and use a spring component. I'd need to use something else to generate all the classes other than xjc. But I cannot find anything that would perform that task
There is a lot of stuff going on here and I have to agree with #BlaiseDoughan you should be able to do this outside of Spring.
Although Spring does do object pooling (aop) and has some management for throw away objects you should not use it for such. Basically anytime your doing getBean during runtime unless your know what your doing your doing it wrong.
Spring is for managing behavior based singletons.
So what you want to do is think how can make a singleton that does the behavior... In your case you want to make a Factory of JaxbWrapper.class (and I don't mean Spring's special bean Factory).
So something like:
public class JaxbWrapperFactory {
Map<String, JaxbWrapper> pool = new ConcurrentHashMap(); // recommend Guava's Cache
public JaxbWrapper create(String ClassName, String packageName) throws ClassNotFoundException, InstantiationException { }
public Object loadXML(String xmlFile, String fileName) throws Exception {
/// use create from above
}
}
Now in Spring you can only wire JaxbWrapperFactory.
If you want to make different strategies for create JaxbWrapper based on the input xml you could make sort of strategy interface and wire in the implementations. But I don't think you need that complexity.
Basically to boil it down these tips:
Be-aware that singletons and most spring managed beans must be thread safe.
Reserve public static methods for utility only as this leads to evil singletons.
Often times for object creation its best to make your own factory pattern.
You might want to take a look at JAXB's factory support.
Is there a simple way to inject simple primitive type parameters (string and int) to the beans?
What i need is to find the guice equivalent of something like this from spring.xml:
<bean id="aBean" ...>
<property name="fieldName" value="aStringValue"/>
<property name="anotherFieldName" value="123"/>
</bean>
The values could be constructor injected, field injected or method injected, but i don't want to use separate named annotation or factory or provider for every value that i need to pass to the bean.
EDIT: my solution
Here is what i finally came to. I think it is closest to what i'm looking for, but any improvements would be welcome.
I found that in the module, i can declare a provider method and use it to set any properties i need:
MyModule extends AbstractModule{
...
#Provides #Named("testBean") MyTestBean createTestBean(MembersInjector<TestBean> mi){
TestBean test = new TestBean();
mi.injectMembers(test);
test.setFieldName("aStringValue");
test.setAnotherFieldName(123);
return test;
}
...
}
The good point is that the Provides method replaces the bind() for the bean and this way the actual line count doesn't increase much.
I'm still not 100% sure about any side effects, but it looks promising.
There is a build in mechanism to inject properties.
Properties File:
name=jan
city=hamburg
Module
#Override
protected void configure() {
Names.bindProperties(binder(), properties);
}
then in your bean, just inject by Name
class Customer {
#Inject
#Named("name")
String name;
....
}
There are a couple different ways you could do this, including your way. The only drawback to using a Provider method is that it's essentially a hand-rolled factory that you have to remember to maintain. (And in this specific case, you're also not getting the benefits of constructor injection).
Absent a Provider method, you have to use a binding annotation of some kind. If #Named won't work for you, then you'd need to create an annotation for each binding.
bindConstant().annotatedWith(FieldName.class).to("aStringValue");
public SomeClass {
public void setFieldName(#FieldName String fieldname) {}
}
In some cases this might require a 1-to-1 annotation per primitive/String instance to be bound. But I try to make my annotations somewhat orthogonal to the actual instance being described, preferring instead to use the annotation to describe the relationship between the bound objects and the injection points.
It's not always possible, but a whole group of related primitives could then potentially be described by a single binding annotation, as long as each primitive type is only used once in the set. So, this could hypothetically work:
bindConstant().annotatedWith(MyAnnotation.class).to("aStringValue");
bindConstant().annotatedWith(MyAnnotation.class).to(123);
Parenthetically, I'm curious why you can't used #Named annotations on the property, but you can use them on the injected bean?
I have a situation where I would like to dynamically create an object through a factory object, but the object needs to be created through the spring context, to allow autowiring of dependencies. I know that there are lots of other ways that I can solve this problem - using a service locator pattern for example - but I'd like to do it this way if possible.
Imagine I have two objects:
class OuterObject {
List<InnerObjectInterface> innerObjs;
...
}
class InnerObject implements InnerObjectInterface{
#Autowired
SomeDependency someDependency;
...
}
I want to create a factory that does something along the lines of:
class OuterObjectFactory {
private innerObject = new InnerObject();
public OuterObject construct(params){
OuterObject o = new OuterObject();
List<InnerObjectInterface> inners = new ArrayList<InnerObjectInterface>();
...
for(some dynamic condition){
...
inners.add(createInnerObject());
...
}
}
public createInnerObject(){
return innerObject;
}
}
My spring-context.xml would looks something like:
<bean id="outerObjectFactory" class="path.OuterObjectFactory" />
<bean id="innerObject" class="path.InnerObject" factory-bean="outerObjectFactory" factory-method="createInnerObject" />
This however, doesn't work. Only one innerObject is ever created, where I want it to act like it has scope="prototype". If I add scope="prototype" to the bean definition:
<bean id="innerObject" class="path.InnerObject" factory-bean="outerObjectFactory" factory-method="createInnerObject" scope="prototype"/>
Then it seems to create many innerObjects, but they aren't correctly wired. My co-worker believes that the documentation found here implies that the factory bean is only used to initialize a bean, but I don't find that obvious.
I'd appreciate it if anyone could clear up my understanding here, and possibly even suggest a better way of modelling the factory pattern with wiring than what I am doing.
Thanks!
I think what you're saying is that you have a factory which is a singleton and you want it to create new objects of which you want a new one each time with full dependency injection. The old way of doing that was Method Injection which you link to above. The new (and arguably cleaner way) is to use a Scoped Proxy. You can either use annotations or regular config but the idea is that you create a proxy around the bean (e.g. the InnerObject). When ever you need a reference to it, spring will automatically provide you with a new copy with the appropriate dependencies inserted.
I wrote some sort of console client for a simple application.
To be more flexible, I thought it would be nice to only depend on java.io.Input-/OutputStream, instead of accessing System.in/out directly.
I renamed the class ConsoleClient to StreamClient, added setters and made sure that the instance fields are used instead of System.in/out.
At the moment my client code looks like this:
ApplicationContext appCtx = new ClassPathXmlApplicationContext("...");
StreamClient cc = (StreamClient) appCtx.getBean("streamClient");
cc.setInputStream(System.in);
cc.setOutputStream(System.out);
cc.run(); // start client
Question:
Is there a way to move lines 3 and 4 into the Spring configuration (preferably constructor injection)?
Thanks for your time.
Use <util:constant ... />:
<util:constant id = "out" static-field="java.lang.System.out" />
I'm not sure that you can explicitly create a bean using System.out (which I think is what you're asking). However you can create a bean that uses a factory class / method to return an object (in this case System.out)
<bean id="streamOut" class="examples.StreamFactory"
factory-method="getSystemOut"/>