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"/>
Related
I have a custom XML config defining a kind of network like this
S1 ---- O1 ---- O2 ---- O3 ---- T1
\
+--- O4 ---- O5 ------------ T2
\
S2---+- O6 --+- O7 ------------ T4
/ /
S3-+ /
/
S4 ------+
Where
S is some kind of data source, like a web socket
O is an operator processing the data
T is the target or data sink
These elements are represented with xml blocks like this:
<source name="S1" address="ws://example/1" type="websocket" dataType="double" />
<operator name="O6" type="threshold">
<input name="S1"/>
<input name="S2"/>
<input name="S3"/>
<property name="threshold" value="10.34" />
<property name="window" value="10.0" />
</operator>
<sink name="T1" type="database">
<input name="O3"/>
</sink>
The dependencies are constructor parameters. My example operator O6 would have a constructor like this:
class ThresholdOperator extends Operator<Boolean> {
public ThresholdOperator(
String name, // "O6"
List<DataSource> sources, // [S1, S2, S3]
double threshold, // 10.34
double window) { // 10.0
...
There could be multiple instances of this class with different constructor parameters. It is possible that a class has more than one constructor. The type parameter of the base class is the output type.
The type attribute determines what concrete class has to be instantiated. The dataType attribute of the source decides which kind of converter (here String to Double) should be injected.
To create the instances I need to figurare out a dependency graph and start instantiating the objects without other objects from my graph as dependency (the sources in this case), then I would create the objects which depend only on objects created in the first step and so on.
So I would basically reinvent something like Spring for my special use case. Is there a way to leverage Spring to create and wire objects in my case? A somewhat crude hack would be to transform my xml config to a beans.xml. But maybe there is a better way using BeanFactory or the like. Or would it be possible to create the Spring meta-model directly?
I'm using Spring 4.3 but the RC of Spring 5 could be an option, if it would help.
Another alternative not yet mentioned here is using XSLT.
The idea is to define xsl that maps your domain-specific xml to spring beans xml (XSLT+XPath should be more than enough to cover your case).
You can then read domain-specific xml, transform it with that xsl and feed the result to spring.
Have a look on StaticApplicationContext. It is stated in the docs that it is:
Mainly useful for testing.
... but it is a full fledged application context that has support for programmatic bean registration.
You can read your domain-specific xml and define beans based on it inside StaticApplicationContext.
This blog post can give you an idea on how to use StaticApplicationContext to define beans with references and constructor args.
A simpler approach to instantiate your objects from the document would be to either
create an XML Schema describing your data format and using JAXB to create your Java classes
annotate your existing Java classes with JAXB annotations
The "crud" hack approach may be a better approach but instead of converting your config xml to beans xml file manually, I suggest you to look at the Extensible XML authoring approach.
The configuration parser, a.k.a. bean definition parser, allows you to build the bean definitions which will eventually be used your application's spring context to instantiate the beans.
This should also eliminate the needs of figuring out the dependency hierarchy manually and instantiation of objects yourself.
Hope it answer your question.
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.
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.
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.