Call method in constructor - scala

I have a Controller with a constructor where I´m injecting a cache, but also I would like to invoke a method in the constructor when the instance is created. I know we can create some auxiliary constructors with
def this(foo:Foo){}
But in my case because is play framework the one that instance my bootstrap is a little bit more complex.
Here my code
class SteamController #Inject()(cache: CacheApi) extends BaseController {
private val GAME_IDS_LIST_API: String = "api.steampowered.com/ISteamApps/GetAppList/v2"
private val GAME_API: String = "store.steampowered.com/api/appdetails?appids="
private val GAME_KEY: String = "games"
def games = Action { implicit request =>
var fromRequest = request.getQueryString("from")
if (fromRequest.isEmpty) {
fromRequest = Option("0")
}
val from = Integer.parseInt(fromRequest.get) * 10
val to = from + 10
loadGameIds()
Ok(html.games(SteamStore.gamesIds(cache.getVal[JSONArray](GAME_KEY), from, to), cache.jsonArraySize(GAME_KEY)/10))
}
private def loadGameIds(): Unit = {
val games = cache.get(GAME_KEY)
if (games.isEmpty) {
get(s"$GAME_IDS_LIST_API", asJsonGamesId)
cache.set(GAME_KEY, lastResponse.get, 60.minutes)
}
}
What I would like is that loadGameIds would be invoked and cached when the class is instantiated.
Any suggestion?
Regards.

If I understand correctly your question, you simply want to add some statements to the main constructor body? If that's the case, you can simply do so in the body of the class itself. In your case, that would look like this:
class SteamController #Inject()(cache: CacheApi) extends BaseController {
...
private val GAME_KEY: String = "games"
loadGameIds() // <-- Here we are calling from the main constructor body
def games = Action { implicit request =>
...
}
...
}
When doing so, it is usually a good idea to perform additional code after the declaration of all vals and vars in your class, to ensure they are properly initialized at the time your additional constructor code runs.

Related

How do I mock a Scala Companion Object with EASYMOCK on Scala 3? [duplicate]

This question already has an answer here:
How to mock an Object in Scala
(1 answer)
Closed 7 months ago.
I have the following code...
class CoreDataSource {
def getConnection = {
println("Getting the connection")
CoreDataSource.getConnection
}
}
object CoreDataSource {
def getConnection: Option[Connection] = {
getDataSource.get.getConnection
}
def getDataSource: Option[DataSource] = {
...
config = new HikariConfig // This has side effects and can't run
...
val pool : DataSource = new HikariDataSource(config) // This has side effects and can't run
...
Some(pool)
}
}
I am trying to mock out the creation of the HikariDataSource and HikariConfig. I tried this...
class CoreDataSourceSpec extends AnyFunSpec with EasyMockSugar {
describe("Core Data Source") {
it("Do something") {
val cdsMock = mock[CoreDataSource.type]
...
}
}
}
But I get
Cannot subclass final class ....CoreDataSource$
What is the proper way to Mock out a companion object using EasyMock
You don't.
Companion object should only perform pure computations (at least don't contain state) which don't require mocking. Most of the time it's purpose is to store factories and instances of type classes (implicits/givens) for your type.
If you store a mutable state (e.g. connection to the database) in companion you messed up. If you have a Java background, think this way: would you mock static methods of a class? (If you're drifting towards PowerMockito you should reconsider your life choices).
Your example shows that you want to store the connection somewhere - storing it in companion is basically global, shared, mutable state which is universally a bad idea, no matter the background.
Create factory of CoreDataSource in its companion, then pass around CoreDataSource instance directly. No issue with mocking that in your tests.
class CoreDataSource(dataSource: DataSource) {
def getConnection: Connection =
dataSource.getConnection
}
object CoreDataSource {
def createHikari(config: HikariConfig): CoreDataSource =
new CoreDataSource(new HikariDataSource(config))
}
// in test:
val dataSource = mock[DataSource]
val coreDataSource = new CoreDataSource(dataSource)
// then mock dataSource.getConnection
Doing it another way requires solving the hard problem that you have 0 reasons to have in the first place. If this companion object is not your but someone else and you cannot rewrite it - wrap it in your own code that you can control and mock easily.
EDIT. In case you are using something like Google Cloud... it still doesn't make sense to store everything in companion and mock it.
// functionality
class MyService(
connection: Connection
) {
def someFunctionality(arg: Arg): Result = ...
}
// in test
// given
val connection = mock[Connection] // mocking DB sounds like a bad idea but whatever
val myService = new MyService(connection)
// when
myService.someFunctionality(arg)
// then
// assertions
// adapter for Google Cloud, other cloud solutions should be similar
class MyFunction extends HttpFunction {
private val config = ...
private val coreDataSource = CoreDataSource.hikari(config)
private val connection = coreDataSource.getConnection
private val myService = new MyService(connection)
override def service(request: HttpRequest, response: HttpResponse): Unit = {
// extract data from request, then
val result = myService.someFunctionality(arg)
// then send result in response
}
}
And if you needed to cache these private vals - what you are caching is NOT related to business logic at all, it merely wires things together, like main in Java which is never tested, nor require testing.
So you could implement it like:
class MyFunction extends HttpFunction {
override def service(request: HttpRequest, response: HttpResponse): Unit = {
// extract data from request, then
val result = MyFunction.myService.someFunctionality(arg)
// then send result in response
}
}
object MyFunction {
// dependency injection and initialization
private val config = ...
private val coreDataSource = CoreDataSource.hikari(config)
private val connection = coreDataSource.getConnection
val myService = new MyService(connection)
}
where wrapper MyFunction is NOT tested, but MyService which does all the job is easily testable.
You should definitely read more about the language, beside the fact that the other answer mentioned (which is you should only contain pure class-level functionalities in the companion object), you cannot do it. Why? Because companion objects are singleton objects of a final class, which can access private states of the companion class itself and vice versa (think of it kind of like static data of the class).
The thing is, companion object actually is an object of a final class (which if you want, I can provide more details about them). Final classes cannot be mocked, simply because they are "final", and their behavior cannot be changed (even by its subclasses). And mocking is all about mocking a class behavior, not an object's behavior.

How to qualify methods as static in Scala?

I have a class
class MyClass {
def apply(myRDD: RDD[String]) {
val rdd2 = myRDD.map(myString => {
// do String manipulation
}
}
}
object MyClass {
}
Since I have a block of code performing one task (the area that says "do String manipulation"), I thought I should break it out into its own method. Since the method is not changing the state of the class, I thought I should make it a static method.
How do I do that?
I thought that you can just pop a method inside the companion object and it would be available as a static class, like this:
object MyClass {
def doStringManipulation(myString: String) = {
// do String manipulation
}
}
but when I try val rdd2 = myRDD.map(myString => { doStringManipulation(myString)}), scala doesn't recognize the method and it forces me to do MyClass.doStringManipulation(myString) in order to call it.
What am I doing wrong?
In Scala there are no static methods: all methods are defined over an object, be it an instance of a class or a singleton, as the one you defined in your question.
As you correctly pointed out, by having a class and an object named in the same way in the same compilation unit you make the object a companion of the class, which means that the two have access to each others' private fields and methods, but this does not mean they are available without specifying which object you are accessing.
What you want to do is either using the long form as mentioned (MyClass.doStringManipulation(myString)) or, if you think it makes sense, you can just import the method in the class' scope, as follows:
import MyClass.doStringManipulation
class MyClass {
def apply(myRDD: RDD[String]): Unit = {
val rdd2 = myRDD.map(doStringManipulation)
}
}
object MyClass {
private def doStringManipulation(myString: String): String = {
???
}
}
As a side note, for the MyClass.apply method, you used the a notation which is going to disappear in the future:
// this is a shorthand for a method that returns `Unit` but is going to disappear
def method(parameter: Type) {
// does things
}
// this means the same, but it's going to stay
// the `=` is enough, even without the explicit return type
// unless, that is, you want to force the method to discard the last value and return `Unit`
def method(parameter: Type): Unit = {
// does things
}
You should follow scala's advice.
val rdd2 = myRDD.map(MyClass.doStringManipulation)
Write this inside the class then it will work as expected.
import MyClass._

Google Guice field injection in scala case class

I am writing Play 2.5 application using Scala. I have following piece of code:
#ImplementedBy(classOf[BarRepositoryImpl])
trait BarRepository {
def bar = //some actions
}
class BarRepositoryImpl extends BarRepository
case class Foo( /*some fields*/) {
#Inject private var barRepository: BarRepository = null
def foo1 = {
val a = barRepository.bar //here barRepository is always null
// some actions with 'a' and returning some result which depends on 'a'
}
}
I also have a controller where I inject BarRepository as well, but through constructor and there everything works well while in the class Foo on the line val a = barRepository.bar I get a NullPointerException. Could someone help to figure out what's the problem? Is it forbidden to use injection in case class?
If you don't want to pollute your case class signature with Guice injected annotation and fields then simply add an implicit dependency on the method that needs it instead:
case class Foo( /*some fields*/) {
def bar1(someField: Int)(implicit barRepository: BarRepository) = {
// some code that interacts with barRepository
}
}
The calling class will have to have the BarRepository as an implicitly injected parameter. E.g. a Play controller like:
#Singleton
class HomeController #Inject()(cc: ControllerComponents)
(implicit barRepository: BarRepository)
extends AbstractController(cc) {
def index() = Action { implicit request =>
val foo = Foo("field")
val bar = foo.bar1
// ...
}
}
I would have assumed that you inject the object in your class signature?
case class Foo #Inject()(barRepository:BarRepository, /* your fields */){
/** some stuff **/
}

Scala equivalent of static final using a companion object

How could I convert the following into scala.
public class JedisDB {
private static final JedisPool jedisPool = new JedisPool(getJedisPoolConfig());
public static JedisPoolConfig getJedisPool() {
// ..
}
public int getTest123() {
jedisPool.getResource();
// code goes here
}
}
I have seen answers do create a class and a companion object, but can someone explain to me exactly how and why I should do this?
Should I create what I want to expose as a static variable in the companion object, and the loading of the configuration file that is used to initialize the jedisPool in the class?
Do I have the option of making jedisPool public or private in the companion object?
Also (not to effect the answer to my question but as a added benefit), I read somewhere but didn't fully understand that this makes pattern makes testing difficult, are there workarounds then?
lazy val jedisPool : JedisPool = {
val poolConfig = createPoolConfig(app)
new JedisPool(poolConfig)
}
To get a resource
val j = jedisPool.getResource()
make sure you return resource after done using it.
jedisPool.returnResource(j)
Basically it does not metter if static methods will go to companion object or any other object. A companion object differs from other objects as it has access rights to the class/trait that other objects do not. But that's not really your's example.
Your sample with companion object:
// -- helpers to be able compile
class JedisPoolConfig { }
class JedisPool(p: JedisPoolConfig) {
def getResource = 1
}
// --
// everythis that should be SINGLETON goes into object
object JedisDB {
private lazy val jedisPool = new JedisPool(getJedisPool)
def getJedisPool = new JedisPoolConfig() // or any other implementation
def otherStaticMethod = new JedisDB().anyVal // wow - got access to private val.
}
class JedisDB {
import JedisDB._
def getTest123() = jedisPool.getResource
private val anyVal = "SomeValue";
// other methods
}
// other - non companion object
object JedisDB2 {
// def otherStaticMethod = new JedisDB().anyVal // no luck - no access
}

Scala problem optional constructor

Imagine this simple piece of code:
class Constructor() {
var string: String = _
def this(s: String) = {this() ; string = s;}
def testMethod() {
println(string)
}
testMethod
}
object Appl {
def main(args: Array[String]): Unit = {
var constructor = new Constructor("calling elvis")
constructor = new Constructor()
}
}
The result is
null
null
I would like to be
calling elvis
null
How to achieve this? I cannot call the method testMethod after the object creation.
Mazi
Your test method is called in the main constructor first thing. There is no way another constructor might avoid it being called before its own code runs.
In your case, you should simply reverse which constructor does what. Have the main constructor have the string parameter, and the auxiliary one set it to null. Added gain, you can declare the var directly in the parameter list.
class Constructor(var s: String) {
def this() = this(null)
def testMethod() = println(s)
testMethod()
}
In general, the main constructor should be the more flexible one, typically assigning each field from a parameter. Scala syntax makes doing exactly that very easy. You can make that main constructor private if need be.
Edit: still simpler with default parameter
class Constructor(var s: String = null) {
def testMethod = println(s)
testMethod
}