Using Service methods inside Utils class [Spring and Kotlin] - spring-boot

I have faced a well-known scenarios whereby I really need to move a number of utilities private functions (that should not have been there in the first place) from my Service class to a utility class. My question is around using service methods in a utility class. I have attempted at the following refactoring:
class Utils(
val serviceIneed : ServiceIneed) {
companion object {
private val someMapper = ObjectMapperConfig.mapper
}
fun someUtility(): ResponseEntity<Any> {
// lots of stuff
return serviceIneed.someFunction()
}
}
Then this is the other service where I need to use the method I have moved to the newly created utility class:
class anotherService(
private val serviceIneed: ServiceIneed
) {
fun someMethod() {
// lots of things happening
val utilityUsage = Utils(serviceIneed).someUtility()
}
}
Is this the correct way to go about this? Can you recommend any approach on refactoring service classes in a way that only service-oriented methods and not helper ones remain in my Service class?
Thank you

Related

How GenericContainer from test containers should be parametrised?

I am getting errors in my IDE about:
Raw use of parameterized class 'GenericContainer' Inspection info:
Reports any uses of parameterized classes where the type parameters
are omitted. Such raw uses of parameterized types are valid in Java,
but defeat the purpose of using type parameters, and may mask bugs.
I've checked documentation and creators use everywhere raw type also:
https://www.testcontainers.org/quickstart/junit_4_quickstart/
f.e.:
#Rule
public GenericContainer redis = new GenericContainer<>("redis:5.0.3-alpine")
.withExposedPorts(6379);
I dont understand this approach. Can Anyone explain how should I parametrize GenericContainer<>?
Testcontainers uses the self-typing mechanism:
class GenericContainer<SELF extends GenericContainer<SELF>> implements Container<SELF> {
...
}
This was a decision to make fluent methods work even if the class is being extended:
class GenericContainer<SELF extends GenericContainer<SELF>> implements Container<SELF> {
public SELF withExposedPorts(Integer... ports) {
this.setExposedPorts(newArrayList(ports));
return self();
}
}
Now, even if there is a child class, it will return the final type, not just GenericContainer:
class MyContainer extends GenericContainer< MyContainer> {
}
MyContainer container = new MyContainer()
.withExposedPorts(12345); // <- without SELF, it would return "GenericContainer"
FYI it is scheduled for Testcontainers 2.0 to change the approach, you will find more info in the following presentation:
https://speakerdeck.com/bsideup/geecon-2019-testcontainers-a-year-in-review?slide=74
If you declare it like
PostgreSQLContainer<?> container = new PostgreSQLContainer<>(
"postgres:9.6.12")
.withDatabaseName("mydb");
the warning also goes away.

How to override spring application properties in test classes? Spring’s #ContextConfiguration breaks when using Kotlin inner classes

I’m currently trying to change some Spring configuration properties in test code (they aren’t static, that’s why).
There’s this odd thing when I try to solve my problem with #ContextConfiguration(initializers = [MyTestClass.Initializer::class]).
and in MyTestClass I defined this:
inner class Initializer : ApplicationContextInitializer<ConfigurableApplicationContext> {
override fun initialize(applicationContext: ConfigurableApplicationContext) {
val values = TestPropertyValues.of("spring.datasource.url=" + postgresqlContainer.jdbcUrl)
values.applyTo(applicationContext)
}
}
(I’m using Testcontainers here... how to get this working might be a separate question, feel free to help me out.)
postgresqlContainer is a member of MyTestClass that I want to access. When I run the test I just get an error:
Caused by: java.lang.IllegalArgumentException: No argument provided for a required parameter: instance of fun com.example.MyTestClass.Initializer.<init>(): com.example.MyTestClass.Initializer
Huh, ok, so I kept debugging a bit and I think it’s Spring’s BeanUtils that isn’t able to handle Kotlin inner classes. If I remove the inner keyword from my inner class BeanUtils can create an instance – doesn’t help me of course, since I need access to the property of the outer class.
I wrote a little test to assert my suspicion:
import io.kotlintest.specs.StringSpec
import org.springframework.beans.BeanUtils
class Thing {
inner class InnerThing {
}
}
class BeanUtilTest: StringSpec({
"instantiate inner class" {
BeanUtils.instantiateClass(Thing.InnerThing::class.java)
// fails :-(
}
})
Question: Is there a workaround? How can I override application properties inside my test in Kotlin?
I just ran into this and, after a long time trying to figure out what was going on, I finally came up with a solution.
You can use a companion object as follows (e.g., for MySql):
#Testcontainers
#ExtendWith(SpringExtension::class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#ContextConfiguration(initializers = [ExampleIntegrationTest.Companion.Initializer::class])
class ExampleIntegrationTest {
companion object {
#Container
#JvmField
val mySqlContainer = KotlinMySqlContainer()
class Initializer : ApplicationContextInitializer<ConfigurableApplicationContext> {
override fun initialize(configurableApplicationContext: ConfigurableApplicationContext) {
TestPropertyValues.of(
"spring.datasource.url=" + mySqlContainer.jdbcUrl,
"spring.datasource.username=" + mySqlContainer.username,
"spring.datasource.password=" + mySqlContainer.password
).applyTo(configurableApplicationContext.environment)
}
}
}
...
}

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
}

Spring framework and java like Object collectors In Scala

In Spring framework and Java world, there is an interesting object collector pattern that I use.
For example consider below -
public interface Calculator {
SomeOutput calculate(SomeInput input);
}
#Component
public class CalImpl1 implements Calculator {
public SomeOutput calculate(SomeInput input){
//some implementation
}
}
#Component
public class CalImpl2 implements Calculator {
public SomeOutput calculate(SomeInput input){
//some implementation
}
}
Now this can easily injected in another class using Spring DI
#Component
public class Main {
//This line collects all to implementors of this and set it here.
#Autowired
public List<Calculator> calculators;
//other methods
}
Now problem is I am not sure how same thing can be achieved in scala. I have done some search and found cake pattern (http://loicdescotte.github.io/posts/scala-di/) used in scala but that didn't seem to achieve same thing as object collectors like above. I also want to follow open close principle which I think gets violated in cake pattern but using object collectors I can easily achieve it.
is there a way achieve same object collectors like implementation in scala?
There are templates in lighbend activator that illustration using spring DI on Play, Akka and Scala applications. Please see this: https://www.lightbend.com/activator/templates#filter:spring
I haven't used Spring as DI, I usually use Guice (explicitly used because it's default on play framework 2) and Implicits parameters both as a compilation DI.
Sample:
class B
class X(x: Int)(implicit c: B)
//DI - mostly define in main method/application
implicit val c: B = new B
val x = new X(2)
Explicitly using java.util.List worked for me. This is not the prettiest solution but it shows that it basically works. Haven't tried that but implementing a corresponding PropertyEditor you could stick with the Scala types.
trait Calculator {
def calculate(input: SomeInput) : SomeOutput
}
#Component
class CalImpl1 extends Calculator {
override def calculate(input: SomeInput): SomeOutput = ...
}
#Component
class CalImpl2 extends Calculator {
override def calculate(input: SomeInput): SomeOutput = ...
}
#Component
class Main #Autowired()(calculators: java.util.List[Calculator]) {
// or inject field if constructor injection is not desired
// #Autowired
// var calculators: java.util.List[Calculator] = _
}
object Main {
def main(args: Array[String]) = {
val ctx = new AnnotationConfigApplicationContext("your package name here")
val main = ctx.getBean(classOf[Main])
// calculators should now be wired in the returned instance
}
}

Dependency Injection with Interface implemented by multiple classes

Update: Is there a way to achieve what I'm trying to do in an IoC framework other than Windsor? Windsor will handle the controllers fine but won't resolve anything else. I'm sure it's my fault but I'm following the tutorial verbatim and objects are not resolving with ctor injection, they are still null despite doing the registers and resolves. I've since scrapped my DI code and have manual injection for now because the project is time sensitive. Hoping to get DI worked out before deadline.
I have a solution that has multiple classes that all implement the same interface
As a simple example, the Interface
public interface IMyInterface {
string GetString();
int GetInt();
...
}
The concrete classes
public class MyClassOne : IMyInterface {
public string GetString() {
....
}
public int GetInt() {
....
}
}
public class MyClassTwo : IMyInterface {
public string GetString() {
....
}
public int GetInt() {
....
}
}
Now these classes will be injected where needed into layers above them like:
public class HomeController {
private readonly IMyInterface myInterface;
public HomeController() {}
public HomeController(IMyInterface _myInterface) {
myInterface = _myInterface
}
...
}
public class OtherController {
private readonly IMyInterface myInterface;
public OtherController() {}
public OtherController(IMyInterface _myInterface) {
myInterface = _myInterface
}
...
}
Both controllers are getting injected with the same interface.
When it comes to resolving these interfaces with the proper concrete class in my IoC, how do I differentiate that HomeController needs an instance of MyClassOne and OtherController needs an instance of MyClassTwo?
How do I bind two different concrete classes to the same interface in the IoC? I don't want to create 2 different interfaces as that breaks the DRY rule and doesn't make sense anyway.
In Castle Windsor I would have 2 lines like this:
container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassOne>());
container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassTwo>());
This won't work because I will only ever get a copy of MyClassTwo because it's the last one registered for the interface.
Like I said, I don't get how I can do it without creating specific interfaces for each concrete, doing that breaks not only DRY rules but basic OOP as well. How do I achieve this?
Update based on Mark Polsen's answer
Here is my current IoC, where would the .Resolve statements go? I don' see anything in the Windsor docs
public class Dependency : IDependency {
private readonly WindsorContainer container = new WindsorContainer();
private IDependency() {
}
public IDependency AddWeb() {
...
container.Register(Component.For<IListItemRepository>().ImplementedBy<ProgramTypeRepository>().Named("ProgramTypeList"));
container.Register(Component.For<IListItemRepository>().ImplementedBy<IndexTypeRepository>().Named("IndexTypeList"));
return this;
}
public static IDependency Start() {
return new IDependency();
}
}
I hope you can use service overrides.
Ex.
container.Register(
Component.For<IMyService>()
.ImplementedBy<MyServiceImpl>()
.Named("myservice.default"),
Component.For<IMyService>()
.ImplementedBy<OtherServiceImpl>()
.Named("myservice.alternative"),
Component.For<ProductController>()
.ServiceOverrides(ServiceOverride.ForKey("myService").Eq("myservice.alternative"))
);
public class ProductController
{
// Will get a OtherServiceImpl for myService.
// MyServiceImpl would be given without the service override.
public ProductController(IMyService myService)
{
}
}
You should be able to accomplish it with named component registration.
container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassOne>().Named("One"));
container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassTwo>().Named("Two"));
and then resolve them with
kernel.Resolve<IMyInterface>("One");
or
kernel.Resolve<IMyInterface>("Two");
See: To specify a name for the component
Typically DI containers follow Register, Resolve and Release patterns. During the register phase there are two steps. The first is to specify the mapping as you are doing. The second step is to specify the rules which govern which to inject where.
This problem is very common when we try to address Cross cutting concerns using decorators. In these situations, you have multiple classes(decorators) implementing a single interface.
Briefly, we need to implement IModelInterceptorsSelector which allows you to write imperative code that decides which Interceptor to apply to which types or members.
This is elaborately described in the book Dependency Injection in .Net book by Mark Seemann. Look for chapter 9 interception or search for the above interface.
I am not an expert at this, but was searching for the exact same problem and found the ans in the above book.
Hope this helps.
Regards
Dev1

Resources