I have two projects in eclipse siteBase and siteCustom
siteBase have controller
public final class BaseController{
#Autowired
BaseService service;
#POST
#Path(/test)
public final boolean test() {
try {
service.test();
}
catch (Throwable ex) {
processException(ex);
}
return true;
}
}
A BaseService Interface
public interface BaseService extends BasicService{
boolean test();
}
And a BaseService Implementation
public class BaseServiceImpl implements BaseService {
public boolean test() {
System.out.println("BaseServiceImpl");
return true;
}
}
And in the siteCustom I have a other Implementation
public class BaseServiceCustomImpl implements BaseService {
public boolean test() {
System.out.println("BaseServiceCustomImpl");
return true;
}
}
As I expect, when I run siteBase and call test controller have a console print:
BaseServiceImpl
And if I run siteCustom and call test controller have a console print:
BaseServiceCustomImpl
(I hope the code it's ok, but it's not problem, it's only for example purpose and It's not tested, it's only to explain the situation)
The other day, suddenly, when I run siteCustom the console show BaseServiceImpl... after some update it again works ok the console shows BaseServiceCustomImpl, but I want to understand exactly how Spring uses the Implementation and when and where decide which Implementation and its methods use.
Related
So far, I had a very simple bean definition that looked like this:
#Bean
#Conditional(value=ConditionClass.class)
SomeInterface myMethodImpl(){
return new ImplementationOne();
}
However, I now have situation where additional implementation class has been added, let's call it ImplementationTwo, which needs to be used instead of ImplementationOne when the option is enabled in configuration file.
So what I need is something like this:
#Bean
#Conditional(value=ConditionClass.class)
SomeInterface myMethodImpl(){
return context.getEnvironment().getProperty("optionEnabled") ? new
ImplementationOne() : new ImplementationTwo();
}
Basically a way to instantiate correct implementation at bean definition time based on the configuration value. Is this possible and can anyone please provide an example? Thanks
It is possible to implement this without using #Conditional.
Assuming you have a Interface SomeInterface and two implementations ImplOne ImplTwo:
SomeInterface.java
public interface SomeInterface {
void someMethod();
}
ImplOne.java
public class ImplOne implements SomeInterface{
#Override
public void someMethod() {
// do something
}
}
ImplTwo.java
public class ImplTwo implements SomeInterface{
#Override
public void someMethod() {
// do something else
}
}
Then you can control which implementation is used in a configuration class like this:
MyConfig.java
#Configuration
public class MyConfig {
#Autowired
private ApplicationContext context;
#Bean
public SomeInterface someInterface() {
if (this.context.getEnvironment().getProperty("implementation") != null) {
return new ImplementationOne();
} else {
return new ImplementationTwo();
}
}
}
Make sure that the component scan of spring finds MyConfig. Then you can use #Autowired to inject the right implementation anywhere else in your code.
I think you are doing it wrong.
You should use #Conditional() on your implementation and not on your Interface.
Here is how I would do it :
The interface you will use on your code.
MyInterface.java
public interface MyInterface {
void myMethod();
}
The first implementation :
MyInterfaceImplOne.java
#Bean
#Conditional(MyInterfaceImplOneCondition.class)
public class MyInterfaceImplOne implements MyInterface {
void myMethod(){
// dosmthg
}
}
MyInterfaceImplOneCondition.java
public class MyInterfaceImplOneCondition implements Condition {
#Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return context.getEnvironment().getProperty("optionEnabled")
}
}
And for the 2nd implementation :
MyInterfaceImplTwo.java
#Bean
#Conditional(MyInterfaceImplTwoCondition.class)
public class MyInterfaceImplTwo implements MyInterface {
void myMethod(){
// dosmthg 2
}
}
MyInterfaceImplTwoCondition.java
public class MyInterfaceImplTwoCondition implements Condition {
#Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return !context.getEnvironment().getProperty("optionEnabled")
}
}
In that case, you now just have to call the interface, and Spring will inject the bean corresponding to the right condition.
Hope it is what you are looking for, and I was clear enough!
How to test a class which depends on Provider<>?
Please see the code below.
class ToTest {
#Inject
Provider<Processor> processorProvider;
public buildData() {
processorProvider.get().process();
}
class ProcessorProviderImpl implements Provider<Processor> {
#Inject
private Handler someHandler;
public Processor get() {
return new MyProcessor(somehandler)
}
}
public static class TestModule extends JukitoModule {
#Override
protected void configureTest() {
bind(Processor.class).toProvider(
ProcessorInstanceProviderImpl.class);
bindMock(SubHandler.class).in(TestSingleton.class);
}
}
class Handler {
#Inject
private SubHandler subHandler; // this is singleton instance
}
}
So when I mock subHandler it doesn't work and when I run unit test I am getting a NullPointerException where subHandler.handle() is getting called.
You can use Providers.of() to initialize processorProvider with a provider of your collaborator instance.
https://google.github.io/guice/api-docs/latest/javadoc/index.html?com/google/inject/util/Providers.html
test = new ToTest();
test.processorProvider = Providers.of(processorMock);
I'm trying to programatically lookup CDI proxies using javax.enterprise.inject.spi.BeanManager.
I'm able to resolve all beans except Instance.
This is the code..
public interface Service {
public void doSomething();
}
public class Serviceimpl implements Service{
public void doSomething(){
system.out.println("Impl clazz");
}
}
public class LoginAction{
#Inject Service svc;
public void logintest(){
svc.doSomething();
}
}
The same functionality works fine as expected when I do this
public class LoginAction{
public void logintest(){
Service svc = BeanManager.getReference(Service.class);
svc.doSomething();
}
}
Although when there is more than one implementation, I'm doing this
public class LoginAction{
#Inject Instance<Service> services;
public void logintest(){
for(Service s : services){
s.doSomething();
}
}
}
And this works perfectly fine. But I'm trying to do the same via BeanManager but it won't work.
public void logintest(){
Instance<Service> svc = BeanManager.getReference(Instance<Service>..); // not sure how to program here. This is where help is needed
for(Service s : services){
s.doSomething();
}
}
The main reason of trying to programatically/canonically lookup is this pience of logic may be in a static block..
I'm trying to figure out why Mockit is not working for the following code:
public class TestClass {
#Test
public void test() {
Mockit.redefineMethods(ExecuterClass.class, new Object() {
#SuppressWarnings("unused")
public SomeService getService() {
return new MockSomeServiceImpl();
}
});
// Code to run test
}
}
public abstract class ExecuterClass<T,U,V,W> {
// Other methods/variables
public SomeService getService() {
return someProvider.getService();
}
}
public interface SomeService {
// Some method definitions
}
public class MockSomeServiceImpl implements SomeService {
// Some method implementations
}
The error I get back is:
java.lang.IllegalAccessError: tried to access class TestClass from class ExecuterClass
Any ideas on how to fix this?? In the end, I would like the test to use the MockSomeServiceImpl methods rather than those in SomeService implementation.
SomeService was generated by a WSDL, so I don't have the implementation that someObject.getService() returns. So I can't do Mockit.redefineMethods(SomeServiceImpl.class, MockSomeServiceImpl.class)
I would like a JUnit 4 test class to implement the same interface as the class its testing. This way, as the interface changes (and it will, we're in early development), the compiler guarantees that corresponding methods are added to the test class. For example:
public interface Service {
public String getFoo();
public String getBar();
}
public class ServiceImpl implements Service {
#Override public String getFoo() { return "FOO"; }
#Override public String getBar() { return "BAR"; }
}
public class ServiceTest implements Service {
#Override
#Test
public String getFoo() {
//test stuff
}
#Override
#Test
public String getBar() {
//test stuff
}
}
When I try this, I get an error: "java.lang.Exception: Method getFoo() should be void",
presumably because test methods must return void. Anybody know of any way around this?
I have to admit, it is a neat trick, though it doesn't scale well to multiple test scenarios.
Anyways, you can use custom runner. For example:
#RunWith(CustomRunner.class)
public class AppTest {
#Test
public int testApp() {
return 0;
}
}
public class CustomRunner extends JUnit4ClassRunner {
public CustomRunner(Class<?> klass) throws InitializationError {
super(klass);
}
protected void validate() throws InitializationError {
// ignore
}
}
A more natural way would probably be to use a code coverage tool, such as Cobertura. It integrates with JUnit nicely AND it shows you cases where your tests may be deficient in some cases (there are many cases such a tool won't catch though).