Spring configured mock giving two different instances - java

Note: I have purposefully removed words from the names of classes and objects, so please excuse the horribly names in my code examples
I've got a test class that sets up my application using some test Spring context files. The application is a wrapper to a web service.
As this is a test, I have mocked the main interface to the web service in question (the ITransporter class). This gives me the ability to set expectations so that I can check that the requests sent to the web service are: in the expected format; have the expected fields complete; etc...
My mock is defined in a file called test-beans-context.xml and is passed into some service beans, as follows:
<bean id="mockTransporter" class="org.easymock.EasyMock" factory-method="createMock" scope="singleton">
<constructor-arg index="0" value="transport.ITransporter" />
</bean>
<bean id="accountService" class="service.AccountService">
<property name="transporter" ref="mockTransporter" />
</bean>
This context file is used in 2 places. (And I fear this is where my problem arises.)
The first being the test class, which is defined as follows:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration( locations={"classpath:test-beans-context.xml"} )
public class AbstractIntegrationTest {
#Autowired
private ITransporter mockTransporter;
//Some tests that perform expectations like the following:
// EasyMock.reset( this.mockTransporter );
// EasyMock.expect( this.mockTransporter.sendRequest( EasyMock.capture(this.requestXmlCapture) ) ).andReturn( responseXml );
}
The second place is in a class that is within the logical trail for getting to sending the request. It loads a separate XML context file /lite-api-context.xml that then imports the test one in my test set up.
public class Factory implements IFactory {
public Factory() {
context = new ClassPathXmlApplicationContext("/lite-api-context.xml");
}
#Override
public IAccountService getAccountService() {
return (IAccountService) context.getBean("accountService");
}
}
And lite-api-context.xml includes this:
<import resource="classpath:/test-beans-context.xml" />
My problem is that in the test class, I'm getting a different instance of the mocked ITransporter to the one that is ultimately being used by my other services. So the expectations I set up are never actually executed as the mocks end up being different instances.
Is there a way to ensure I get the same instance in both places?
Or am I going to have to create my own singleton test implementation of the ITransporter interface? (Basically creating a stub that behaves exactly like my mock does now.)
EDIT: (Answer)
As The Thom said, it appears I need to create my own class to manage the mock.
I wanted to add my solution here too in case anyone stumbled across a similar problem.
Just wrote a quick static class like this:
public class MockTransporter {
private static ITransporter mockTransporter = EasyMock.createMock(ITransporter.class);
public static final ITransporter getInstance() {
return mockTransporter;
}
}
And had to change the XML config to this:
<bean id="mockTransporter" class="MockTransporter" factory-method="getInstance" />

Oh yeah, that's a problem. When you create a new context that's like creating a new object space for Spring. The one created in your XML file is different from the one created in your handmade context. They will always produce different variables.
I've been burned on that one before.
You're only hope if you want the same ones is to manage your own singletons.

The ideal way to solve this problem would be to create the Factory as a Spring bean as well, and inject the AccountService into the Factory bean.
In general context.getBean() should be avoided in production code because it harms the concept of Inversion of Control (for more information see: Why is Spring's ApplicationContext.getBean considered bad?). It's okay to use it in test code though.

Related

How to avoid using ApplicationContext.getBean() when implementing Spring IOC

I'm just getting started with Spring IOC concept. I often see most of the examples found in the internet use the code to get the object.
ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Hello hello = (Hello) appContext.getBean("hello");
As a reference from these questions 1 and 2 in the stackoverflow. I've inferred that, it's not necessary to use appContext.getBean("hello") in the code which is considered to be the bad practice. Also, not recommended anymore. Correct me right here, If my inference is wrong.
Keeping that in view, I have made changes in my project accordingly.
Here's my applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<bean id="utilClassRef" class="org.hd.derbyops.DUtils" lazy-init="false" />
<bean id="appContext" class="org.hd.derbyops.ContextProvider" lazy-init="false">
<property name="utils" ref="utilClassRef" />
</bean>
</beans>
My contextProvider Class Code
public class ContextProvider implements ApplicationContextAware {
private static ApplicationContext ctx;
/**
* Objects as properties
*/
private static DUtils utils;
public void setApplicationContext(ApplicationContext appContext)
throws BeansException {
ctx = appContext;
}
public static ApplicationContext getApplicationContext() {
return ctx;
}
public static DUtils getUtils() {
return utils;
}
public void setUtils(DUtils dUtilsRef) {
utils = dUtilsRef;
}
}
For instance, consider a class A that depends on org.hd.derbyops.DUtils.
I'm using the following code line
ContextProvider.getUtils();
inorder to get DUtils Object in class A, thus avoiding usage of ApplicationContext.getBean() anywhere in my code.
Assume, if I have 10 classes and my class A is dependent on all of them, whose objects to be created and accessed without using ApplicationContext.getBean(). In that case also, as done above, I have a thought of creating properties of ContextProvider class followed by setter's and getter's of that property, where in get<PropertyName> is static. So that, I can use it wherever I'm in need of an object, like this
ContextProvider.get<PropertyName>;
Here's my brief question.
Firstly, Is my approach right? If it's right, loading all the beans at the start-up, wouldn't it be a performance killer? How would you do that in your applications without calling getBean atleast more than once?
If you were to design a web-application & you were to implement Spring IOC, without using ApplicationContext.getBean() in any of the code. How would you do that?
Note: with reference to the other questions tagged above
Calling ApplicationContext.getBean() is not Inversion of Control!
The simple answers are yes and no, no, and no. And finally, do a search online for spring MVC, as this probably does what you want.
So, your approach. Yes, you've got most of it right. However, it's considered very bad practice to use static methods for everything. And, you don't need to. Spring is based on the idea that you can simply create normal pojos, and spring will use them as singletons, and inject them into one another (it can also create objects on the fly, but I'm going for the common case here). If you use static classes and methods then:
You can't mock them for unit testing (you're using JUnit right?)
You can't use them with inheritance
Static initialisers are a great way to loose exceptions
etc, etc
So, yes to injection, and no to static stuff.
Next, performance. You're right in that it's a lot slower to use spring, but, if you do all your injection on startup it only happens once. Spring is meant for server side applications where there is likely to be a number of singleton classes passing data around. So, there might be a class to get stuff from a DB, one to process it, and one to display it, and spring is used to wire them together.
If you're using spring in an application where you start up repeatedly, like a command line app, then you are using it for the wrong sort of application, and you probably want to use a builder or something. Spring is meant for big enterprise apps that aren't restarted often.
Finally, if you simply inject all the dependencies for a class into it at startup, and you do this with all your classes, then you don't need to do any getBean stuff at all. Also, using the init-method and destroy-method attributes on a bean means that you can start up processes once spring has finished injecting dependencies. You need only load the context, and your app will spring (pun intended) into existence.
As for web projects, Spring MVC basically takes the whole inversion of control pattern and applies it to web applications. The spring stuff gets loaded by the container, and you can define the URLs to respond to using nothing more than bean names. And most of your code can stay as pojos. If you have something insanely complex, you may want to look at spring web flow, but I'd advise you to make sure that your spring foo is very strong before attempting that.
Here's my example for getting the first instance without actually calling getBean() on ApplicationContext.
public class Test{
// Declare private static variable so that we can access it in main()
private static Triangle triangle;
// Use constructor injection to set the triangle
public Test(Triangle triangle) {
Test.triangle = triangle;
}
public static void main(String[] args) {
// Specify the context file containing the bean definitions
// Spring automatically creates instances of all the beans defined
// in this XML file. This process is performed before you actually make
// a getBean("beanName") call.
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
// Use instance methods of triangle
Test.triangle.draw();
}
}
You can use another way:
In spring.xml (Your bean configuration XML file)
<bean class="com.example.Test" init-method="myMethod">
<constructor-args ref="triangle"/>
</bean>
Now for your main class
public class Test {
private final Triangle triangle;
public Test (Triangle triangle) {
this.triangle = triangle;
}
public static void main (String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
}
// Called by Spring immediately after the Triangle Bean has been created and
// all the properties for the bean have been set. This method name must match
// the one specified with destroy-method attribute in spring.xml
public void myMethod () {
triangle.draw();
}
}

How to design beans in spring framework

I am new to Spring framework. Maybe this is more of a Java EE bean design question than related to Spring framework. Anyway, I just shoot it and see how clear I can make myself.
So I have a service. The service takes a connection string as constructor parameter. Then you can use the service to upload files to the location indicated by the connection string.
So you will start with something like:
public class MyService{
public MyService(String connectionStr){ ... }
}
When you need such a service, you call:
MyService service = new MyService("xxx");
...
That's what I used to do. Nothing fancy. Now if I do it in Java under Spring, I somehow want the service to be a bean. I need to do this:
#Component
public class MyService{
#Autowired
public MyService(#Value(...some connection string...) String connectionStr) {...}
}
But I get confused how you can inject dependency in compile time? I never know what connection string I will pass to create the service. When I read Spring tutorials, most of them have parameters coded in XML config file. Can I design a Spring bean like the one above but require the parameters to be passed in runtime?
Thanks.
You can design a method like this:
void upload(String location,XXX other parameters);
I didnt really get your question but will try to answer.
Check here or google to check if you really want to go for spring.
Coming to your query, For your service you would have to define some thing like this in your spring context.
<bean id="myService" class="com.blah.MyService">
<constructor-arg>
<value>http://HOST/test/</value>
</constructor-arg>
</bean>
Your service class will be,
public class MyService{
public MyService(String connectionString) {...}
}
This is how you will call your service in your application
ApplicationContext context = new ClassPathXmlApplicationContext(
new String[] { "context.xml" });
MyService service = (MyService) context
.getBean("myService");
The above can be implemented using annotations also. Check here for more details

using spring, can I extract some part of a static method to use to set a property on a bean?

I have a static method I have no control over: MyUtils.getServiceURL() which returns a URL. I need to extract just the port from this URL to set a property on a bean:
<bean id="myBean>
<property name="defaultPort" value="?????"/>
</bean>
I can get the string value of the URL as a bean like this:
<bean id="serviceURL" class="MyUtils" factory-method="getServiceURL" />
I'm probably just going to write a method to parse the URL in myBean and extract the port. I was wondering if there was a way to avoid having to do this, and configure this directly in the spring context?
No need for custom classes, or parsers. Remember, a bean is just a class with get/is/set methods. A java.net.URL class qualifies as such.
Solution: Use a java.net.URL as a Spring-configurable bean and call it's getPort method.
Remember, in Spring, you can wire anything as a bean very easily so long as it sports methods using the get/is/set Bean convention. The java.net.URL class does such a thing.
** warning ** I'm just typing this out of my a$$, you'll have to check for any syntax shenanigans that I might be introducing in this Spring-config pseudo-code. One thing that is certain is that the concept will work with Spring 2.5 and that it relies on the util schema.
If you are using an older version of Spring, you'll have to use a PropertyPathFactoryBean. If you are using Spring 3.0, you'll want to use Spring expression language (EL), but I can't comment on the later since I'm not familiar with Spring 3.0.
In java:
int port = (new URL(MyUtils.getServiceURL()).getPort()
In Spring:
<bean id="serviceURL" class="MyUtils" factory-method="getServiceURL" />
<bean id="myURL" class="java.net.URL">
<constructor-arg>
<ref-bean="serviceURL"/>
</constructor-arg>
</bean>
<util:property-path id="defaultPort" path="myURL.port"/>
<bean id="myBean>
<property name="defaultPort" ref="defaultPort"/>
</bean>
There might be a way to consolidate all these four expressions into three or less, don't know if that will improve readability, though. The concept remains the same, though. Treat a java.net.URL instance as a bean, set its URL via its constructor, and get a hold (via Spring) of its getPort() method.
** edit **:
If you are using Spring 2.5 you can create an inline groovy bean that does all that for you. I've seen people doing that as integration glue to get rid of multitude of temp Spring bean place holders. That's the best choice IMO when you need to define a class (when it's simpler than just using Spring tags) and when you know such a class won't be used outside of Spring wiring of things.
Not I can think of. Either way, you probably have to write something to parse the port out. Since you have no control of that static method, perhaps you may want to utilize the adapter pattern to hide that static method. Doing so also makes your code easier to test because you can easily mock that external API out. For example:-
public interface URLServiceAdapter {
int getServiceURLPort();
}
public class URLServiceAdapterImpl implements URLServiceAdapter {
public int getServiceURLPort() {
return MyUtils.getServiceURL().getPort();
}
}
Your beans will then rely on your adapter class instead of MyUtils.getServiceURL() directly:-
<bean id="urlServiceAdapter" class="project.URLServiceAdapterImpl" />
That way, you can do something like this:-
#Autowired
private UrlServiceAdapter urlServiceAdapter;
...
bean.setDefaultPort(urlServiceAdapter.getServiceURLPort());
SpEL is your friend.
<bean id="myBean>
<property name="defaultPort"
value='#{ T(com.foo.MyUtils).getServiceURL().split(":")[2].split("/")[0] }'/>
</bean>
Enjoy,

injecting mock beans into spring context for testing

I know similar questions have been asked, e.g. here, but having done a search, I've come upon a solution I'm much happier with here
My only problem however, is that I'm not sure how to implement this solution.
What I want to be able to do is via the HotswappableTargetSource override the bean definitions of select beans in my application context with my test versions and then run the test.
Then for each test case I'd like to specify which beans I want to be hot swappable and then each test must be able to create its own mock versions and swap those in, and be able to swap back again.
I am able to get the Application Context the test is running with but what I don't know is how to configure a bean to be hot swappable. I know how to do it when configuring beans with xml but I don't want to go back to using xml to configure beans.
UPDATE: There's a library that does it!
https://bitbucket.org/kubek2k/springockito/wiki/springockito-annotations
The solution is as follows:
You will need to change the spring context of your application to proxy the bean you want to swap:
<bean id="beanSwappable" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="targetSource" ref="beanSwap" />
</bean>
<bean id="beanSwap" class="org.springframework.aop.target.HotSwappableTargetSource">
<constructor-arg ref="beanToSwap" />
</bean>
beanSwap is the proxy onto this beanSwap.
beanSwappable is the bean which you reference when you want to swap the bean
beanToSwap is the default implementation of the bean
Thus a change to the system under test is necessary.
And in your test the code will look like:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "test.xml", "spring.xml" })
public class Test {
#Resource(name="beanSwappable")
Bean b;
#Resource(name = "beanSwap")
HotSwappableTargetSource beanSwap;
public void swap() {
Bean b = << create mock version >>
beanSwap.swap(b);
// run test code which
}
}

Auto-cast Spring Beans

Is there a way to auto-cast Spring beans to the class defined in the application context XML? I'd like to avoid putting type information about the beans in 2 places.... in the xml configuration file and also in the code as a cast.
For instance, given this config file
<bean id="bean-name" class="SimpleSpringBean" scope="prototype">
<property name="myValue" value="simple value"></property>
</bean>
Can I call ApplicationContext.getBean("bean-name") in such a way as to avoid directly casting the return type to SimpleStringBean. I know I can also call ApplicationContext.getBean("bean-name", SimpleSpringBean.class) to avoid the cast itself, but I still have the type info in 2 places.
It seems that Spring can get the class info (ApplicationContext.getType) or by getting the type from the bean itself, but no way to automatically cast the type without programmer intervention.
I agree with Sii, you should avoid calling getBean as much as you can. Just wire your beans to classes that depends on them.
Still, if you have a single class that holds the application context, you can provide a wrapper generic method like the following:
class MyContextHolder{
ApplicationContext appContext;
......
#SuppressWarnings("unchecked")
public static <T> T getBean(String beanName)
{
return (T)appContext.getBean(beanName);
}
}
Then you can call it without casting
MyClass mc = MyContextHolder.getBean("myClassBean");
The answer is you shouldn't be using ApplicationContext.getBean() at all if it's possible, and bear with the one place you have to in the bootstrap code. (Generally, you should never need to use getBean() outside of your application's entry points.)
Also, what you're asking is likely impossible in the Java language at all. Casting is a compile-time feature, combined with a runtime check. The return type of getBean() simply must be known at compile time. Even if Spring can determine the type of an object, it can't change its own method signatures at runtime.
Another thing is that even if this were possible, the feature wouldn't be all that useful. Because Spring AOP is implemented using dynamic proxies, you nearly always want Spring to hand you an instance of an interface the bean implements (which could be an AOP proxy), not of the implementation class.
Another approach I also use is autowiring the bootstrapping class using:
public class Main {
#Autowired FooFacade foo;
#Autowired BarFacade bar;
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("appCtx.xml");
AutowireCapableBeanFactory bf = ctx.getAutowireCapableBeanFactory();
Object main = bf.createBean(Main.class,
AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT,
false);
((Main) main).run();
}
private void run() {
foo.doBootstrapStuff();
bar.doMoreBootstrapStuff();
}
}
(Code done from memory. Might only work if you have the Spring context configured to process wiring annotations, in that case making setters for foo and bar should work.)
The main reason for getBean being untyped is the compatibility of Spring (up to version 2.5.x) with Java 1.4. Spring 3.0 will drop that and thus offer typed getBean method then.
Nevertheless you should avoid looking up beans directly and minimize its usage as far as possible.
What if I use Spring as an object factory that my application uses extensively.
That is, instead of writing a bunch of classes that already inherit or wrap around
known Java classes I just decide to move all that into an xml file to cut down on
lines of Java code. This will mean many lines of xml but I won't need to make
skeleton Java classes which I inject with Spring or autowire. Thus making the lines
of Java code less.
For this reason and still as I am new to Spring I have just as stated in previous
posts used static Java methods which wrap around the getBeans().
I have worked with Spring but it is still new to me so forgive my question.
"Because Spring AOP is implemented using dynamic proxies, you nearly always want Spring to hand you an instance of an interface the bean implements (which could be an AOP proxy), not of the implementation class"
So there is no way to get a dynamic proxy using getBean(), then whats the best practice if there are no interfaces and its a stand alone driver class to be executed?

Categories

Resources