How to dynamically select a service in Grails - spring

From my controller I would like to dynamically select a service based on a parameter.
Currently I have a base service and some other services that extent this base service. Based on the parameter I call a class that does creates a bean name based on the param and eventually calls the following:
import org.codehaus.groovy.grails.web.context.ServletContextHolder as SCH
import org.codehaus.groovy.grails.web.servlet.GrailsApplicationAttributes as GA
class Resolver {
def ctx
def getBean(String beanName) {
if(!ctx) {
ctx = SCH.servletContext.getAttribute(GA.APPLICATION_CONTEXT)
}
return ctx."${beanName}"
}
}
This returns the service I want. However I feel rather dirty doing it this way. Does anyone have a better way to handle getting a service (or any other bean) based on some parameter?
Thank you.

ctx."${beanName}" is added to the ApplicationContext metaclass so you can do stuff like def userService = ctx.userService. It's just a shortcut for ctx.getBean('userService') so you could change your code to
return ctx.getBean(beanName)
and it would be the same, but less magical.
Since you're calling this from a controller or a service, I'd skip the ServletContextHolder stuff and get the context by dependency-injecting the grailsApplication bean (def grailsApplication) and getting it via def ctx = grailsApplication.mainContext. Then pass it into this helper class (remember the big paradigm of Spring is dependency injection, not old-school dependency-pulling) and then it would be simply
class Resolver {
def getBean(ctx, String beanName) {
ctx.getBean(beanName)
}
}
But then it's so simple that I wouldn't bother with the helper class at all :)

Related

How to mock private method in public method in Spring Boot with JUnit

I'd like you ask a few questions and ask you for advice:
I want to test my public method (I use Spring Boot, Mockito, JUnit):
#Service
public class MyClass{
public Long getClientId(List<String> nameSurname) throws AuthorizationException {
Long operatorId;
if(...){
(... something not interesting ...)
User user = getUserByLogin("AnthonyGates2");
operatorId = nonNull(user) ? user.getOperatorId() : null;
} else {
List<User> users = getUserListByLogin("AnthinyGates");
operatorId = isNotEmpty(users) ? return operatorId;
return operatorId;
}
How to test the method getClientId?
Methods getUserByLogin and getUserListByLogin are private in this class (MyClass) but I have to mock the results of these private methods because these methods retrieve data from an external service.
These private methods looks like:
User user = DelegateImpl.getDelegate().getUserByLogin(nameAndSurname);
DelegateImpl.getDelegate().getUserByLogin get data from database and that data have to be mocked like:
when(DelegateImpl.getDelegate().getUserByLogin(any())).thenReturn(user);
How can I test my public class? Should I use PowerMock/PowerMockito? Making these methods public is in my opinion ugly because these methods are called only in MyClass. I can't find a good tutorial in Internet for my case (Spring Boot, Mockito, JUnit).
Thank you very much for all your tips!
Best regards
Matthew
Test the unit only by calling the public methods. I think that your example is a class in the service layer (contains business logic) and the two getUser... methods should be in a different class (I think in the data layer) where they can be public. Inject that class via the constructor as a dependency (in the service object) so you can mock it when testing the service class. The data layer class (with the getUser... methods) can also be tested by it's own unit tests.
If you are not able to unit test a method/class then it most probably means that it just does too much. Try extracting your private methods to a separate class. It does not need to be public - you can e.g. have it package-local in the same package.
Later, in the test, you would have to inject a mock of this class and simulate its behaviour.
The setup of MyClass in its unit test could look similar to this:
AnotherClass anotherClassMock = Mockito.mock(AnotherClass.class);
MyClass myClass = new MyClass(anotherClassMock);
Where AnotherClass would have methods getUserListByLogin and getUserByLogin.
EDIT:
It seems that the logic within in your private methods already call an external class. The problem is that you obtain an instance of an object via a call to a static getDelegate() method in another class.
Here's what you can do:
Create a new field in MyClass which would have the same type as the one returned by getDelegate() method (I don't know what that is, I'll call it Delegate)
Have 2 constructors: a default one which would assign the result of getDelegate method to your new field and another one which would take an instance of Delegate as a parameter and assign it to your field
In tests use the second constructor to create an instance of MyClass and pass a mock of Delegate class
It would look more ore less like this:
class MyClass() {
private Delegate delegate;
MyClass() {
this.delegate = DelegateImpl.getDelegate();
}
MyClass(Delegate delegate) {
this.delegate = delegate;
}
// ... the rest
}

Writing a testable Finagle Resolver

I'd like to test a Finagle Resolver properly.
Let's get a sample code:
import com.twitter.finagle.{Addr, Address, Resolver}
import com.twitter.util._
class DummyResolver extends Resolver {
override val scheme: String = "sample"
override def bind(arg: String): Var[Addr] = {
val delegate = SomeFactory.fromArgs(arg).build()
Var.async(Addr.Pending: Addr)(u => addrOf(u)(delegate))
}
}
The use of a static factory prevents me from unit-testing the resolver.
As far as I know, the only way to provide the resolver to Finagle is to declare it into the com.twitter.finagle.Resolver file in META-INF/services. Thus, I cannot provide an instance myself.
Given those constraints, how to design the resolver to either:
be able to provide an instance of the delegate,
or be able to properly test the behavior (and mock the delegate)?

What's the best pattern for injecting a bean with arguments?

I have a number of cases in my app where client code wants to create a bean on-demand. In each case, the bean has 1 or 2 constructor arguments which are specified by the client method, and the rest are autowired.
Ex:
//client code
MyQuery createQuery() {
new MyQuery(getSession())
}
//bean class I want to create
//prototype scoped
class MyQuery {
PersistenceSession session
OtherBeanA a
OtherBeanB b
OtherBeanC c
}
I want A, B, and C to be autowired, but I have the requirement that 'session' has to be specified by the calling code. I want a factory interface like this:
interface QueryFactory {
MyQuery getObject(PersistenceSession session)
}
What's the most efficient way to wire up the factory? Is it possible to avoid writing a custom factory class that does new MyQuery(...)? Can ServiceLocatorFactoryBean be used for something like this?
You can use the #Autowired annotation on your other beans and then use the ApplicationContext to register the new bean. This assumes otherBeanA is an existing bean.
import org.springframework.beans.factory.annotation.Autowired
class MyQuery {
#Autowired
OtherBeanA otherBeanA
PersistenceSession persistenceSession
public MyQuery(PersistenceSession ps){
this.persistenceSession = ps
}
}
I'm not positive if this is the most efficient way to create a new bean, but it seems to be the best way at runtime.
import grails.util.Holders
import org.springframework.beans.factory.config.ConstructorArgumentValues
import org.springframework.beans.factory.support.GenericBeanDefinition
import org.springframework.beans.factory.support.AbstractBeanDefinition
import org.springframework.context.ApplicationContext
class MyQueryFactory {
private static final String BEAN_NAME = "myQuery"
static MyQuery registerBean(PersistenceSession ps) {
ApplicationContext ctx = Holders.getApplicationContext()
def gbd = new GenericBeanDefinition(
beanClass: ClientSpecific.MyQuery,
scope: AbstractBeanDefinition.SCOPE_PROTOTYPE,
autowireMode:AbstractBeanDefinition.AUTOWIRE_BY_NAME
)
def argumentValues = new ConstructorArgumentValues()
argumentValues.addGenericArgumentValue(ps)
gbd.setConstructorArgumentValues(argumentValues)
ctx.registerBeanDefinition(BEAN_NAME, gbd)
return ctx.getBean(BEAN_NAME)
}
}
Instead of using Holders, it's advised to use the ApplicationContext from dependecy inject if available, you could then pass this to the registerBean method.
static MyQuery registerBeanWithContext(PersistenceSession ps, ApplicationContext ctx) {
...
}
Calling class:
def grailsApplication
...
PersistenceSession ps = getRuntimePersistenceSession()
MyQueryFactory.registerBean(ps, grailsApplication.mainContext)
I changed the name of the method to truly reflect what it's doing - registering a spring bean as opposed to instantiating a MyQuery. I pass back the bean using the getBean method, but you also have access to the same bean using the ApplicationContext once it's been created.
def myQueryBean = MyQueryFactory.registerBean(ps)
// or somewhere other than where the factory is used
def grailsApplication
def myQueryBean = grailsApplication.mainContext.getBean('myQuery')

Grails inject Service into Controller dependant on environment

I have a situation in a Controller where I'm surrounding pieces of code in if(Environment.Current == Environment.PRODUCTION) blocks because the block of code is calling methodA in restService that makes a REST call to a URL that is only available when the app is deployed onto a specific production server. However doing so means that area of code is unreachable when running tests, which makes me a bit uncomfortable.
In the Development environment I'm not concerned with making the call to methodA as I'm stubbing out what the methodA would return and passing it on to the next Controller, so changing the if statement to if(Environment.Current != Environment.DEVELOPMENT) allows me to test the code better and not have to make calls to places I can't reach during dev.
Ideally though I would like to try and inject a Service into a Controller dependent on the grails environment; so I could have two Services like this:
class RestService {
def methodA() {
// go do a REST call
}
}
and
class FakeRestService() {
def methodA() {
// return some stubbed response
}
}
and in my Controller restService would be an instance of FakeRestService in DEVELOPMENT and TEST environments, and an instance of RestService in PRODUCTION
class SearchController {
def restService
def index() {
restService.methodA()
}
I'm a bit stumped on how I could achieve this in a 'Grailsy'/Spring way. I've been looking into creating some sort of Service Factory which would return an instance of either RestService or FakeRestService dependent on the environment, but it would be nice if I could define what Service to inject into restService in config or something similar.
Any advice would be great!
You can add an alias for the bean name in resources.groovy when environment is TEST.
import grails.util.Environment
beans = {
if ( Environment.current == Environment.TEST ) {
springConfig.addAlias 'restService', 'fakeRestService'
}
}
RuntimeSpringConfiguration is available in resources.groovy by getSpringConfig().
Here is a more Grails-y version of dmahapatro's answer:
import grails.util.Environment
beans = {
Environment.executeForCurrentEnvironment {
environments {
development {
springConfig.addAlias 'restService', 'fakeRestService'
}
}
}
}

How to use the Facade.Instance method without object construction?

I only recently completed a unit on software patterns and am now attempting to comprehend the PureMVC framework. One thing has got my stumped however, something which is simple to the gurus here.
I'm attempting to create an instance of the singleton Facade class. In the constructor, the comments state:
This IFacade implementation is a Singleton, so you should not call the constructor directly, but instead call the static Singleton Factory method Facade.Instance
How can you call the instance method when the Facade object has not even been created?
The Facade.Instance method looks like this:
public static IFacade Instance
{
get
{
if (m_instance == null)
{
lock (m_staticSyncRoot)
{
if (m_instance == null) m_instance = new Facade();
}
}
return m_instance;
}
}
You are accessing a static property. Static properties are part of the class definition, not class instances. To access a static member (property, field, method), simply use the class name dot member:
var myFacade = SomeClass.Instance;

Resources