Play framework interactive console - Access class which has DI - read-eval-print-loop

Im using Play 2.6.
I use sbt console to get into the interactive console.
Im using this link to bootstrap the app
https://www.playframework.com/documentation/2.6.x/PlayConsole#launch-the-interactive-console
Ive a typical model which is as below
#Singleton
class UserRepository #Inject() (#NamedDatabase("mysql") dbConfigProvider: DatabaseConfigProvider)(implicit ec: ExecutionContext) {
How do I get access to the singleton instance of UserRepository inside the REPL ?

Im using this link to bootstrap the app https://www.playframework.com/documentation/2.6.x/PlayConsole#launch-the-interactive-console
This will give you access to the app
import play.api._
val env = Environment(new java.io.File("."), this.getClass.getClassLoader, Mode.Dev)
val context = ApplicationLoader.createContext(env)
val loader = ApplicationLoader(context)
val app = loader.load(context)
Play.start(app)
// Now to load my classwith all the dependencies injected and ready to use
val c = Class.forName("user.UserRepository")
val repo = app.injector.instanceOf(c).asInstanceOf[user.UserRepository]
repo.list

Related

Kotlin top level function not visible when used from other Maven project

The following code works from within the same project:
import org.slf4j.Logger
import org.slf4j.LoggerFactory
val Any.log: Logger
get() = LoggerFactory.getLogger(this.javaClass)
Example usage:
log.info("hi!")
When I try it from another project I get a compilation error:
Cannot access 'log': it is internal in 'com.mycompany'
Why is this happening and how can I make it work?
I don't get it entirely but I've figured it out. It does work like this:
class Logger {
companion object {
val log: Logger
get() = LoggerFactory.getLogger(this.javaClass)
}
}

Exporting several services using Service Component Runtime

For example i have component exporting simple web-service:
#Component(
property = ["osgi.jaxrs.resource=true"],
configurationPid = ["some.file.config"]
)
#Path("/service")
open class Service {
#GET
#Produces("text/plain")
#Path("/getData")
fun getData(): Response = Response.ok("Some data").build()
#POST
#Consumes("text/plain")
#Path("/setData")
fun registered(inputData: String): Response = Response.ok().build()
}
Is creating another component only way to publish another service ? Can i do this somehow using single component ?

I am getting a compile time error when trying to implement the hateos , It is not showing me the methodOn method

I am trying to implement the Hateoas using spring boot.
In my UserController class i have used the below code
#GetMapping("/users/{id}")
public Resource<User> retrieveUser(#PathVariable int id) {
User user = service.findOne(id);
Resource<User> resource = new Resource<User>(user);
ControllerLinkBuilder linkTo=linkTo(methodOn(this.getClass()).retrieveAllUsers());
I am getting a compile time error on line where i am using the - methodOn().
Compiler is not able to find the methodOn using the controller link builder.
I have used the below import to implement hateoas
import org.springframework.hateoas.mvc.ControllerLinkBuilder.*;
Methods you are using here are static, so to use them you need access using class reference unless you import them using static imports. See more details here

Can I create a CronJob and a Job in the web context?

Normally, we can create CronJobs and Jobs (which extends AbstractJobPerformable) by definining configuration in *-items.xml and in *-spring.xml. However, I can't get these jobs to access the beans in the web context. Can I create a CronJob and a Job in the web context? If yes, how?
The reason I need the jobs to work in the web context is I need to access the ehcache, and manipulate it.
You don't need to create the job in your web context. Create an own extension for this job and a dependency to your facades extension.
If you'd like to keep using default cronJobService to run your jobs then, probably, the only solution would be to 'correctly' get access to a required web context.
Sample groovy script to get access to web application context by its name.
import org.springframework.cache.ehcache.EhCacheCacheManager
import org.springframework.web.context.ContextLoader
final String WEB_CONTEXT_NAME = "/rest"
def contextLoader = ContextLoader.currentContextPerThread.find { it.key.contextName == WEB_CONTEXT_NAME }
assert contextLoader != null
def webApplicationContext = contextLoader.value
webApplicationContext.getBean(EhCacheCacheManager)
Keep in mind that ContextLoader.currentContextPerThread is a private field. To access the field in java you can use
def f = ContextLoader.getDeclaredField("currentContextPerThread");
f.setAccessible(true);
Map<ClassLoader, WebApplicationContext> contexts = f.get(HybrisContextLoaderListener);
Sample JobPerformable will be looking like
public class WebContextAwareJob extends AbstractJobPerformable<CronJobModel> {
#Override
public PerformResult perform(final CronJobModel cronJobModel) {
final CacheManager cacheManager = getEhCacheManager().getCacheManager();
final Cache cache = cacheManager.getCache("");
}
private EhCacheCacheManager getEhCacheManager() {
return getRegistry().getBean(EhCacheCacheManager.class)
}
private WebApplicationContext getRegistry() {
<see sample code above>
}
}

NullpointerException: cannot get property on null object

Working on IDEA and trying to launch the following code:
package com.myCompany.routing.spring
import com.dropbox.core.DbxRequestConfig
import grails.util.Holders
import spock.lang.Specification
class DropboxSpringConfigSpec extends Specification {
def grailsApplication=Holders.grailsApplication
def "It instantiates and configures the dropboxRequestConfig component"() {
given:
def ctx = grailsApplication.mainContext
//do stuff...
}
}
I get the following error:
java.lang.NullPointerException: Cannot get property 'mainContext' on null object
at com.myCompany.routing.spring.DropboxSpringConfigSpec.It instantiates and configures the dropboxRequestConfig component(DropboxSpringConfigSpec.groovy:20)
I've recently made a pull on my VCS, so the code should work.
When running the test as Grails test, I get the following error:
Error |
2015-03-04 13:32:00,989 [localhost-startStop-1] ERROR context.GrailsContextLoader - Error initializing the application:
Missing configuration in Config.groovy: connection.uri.
Okay, it seems some configurations in Config.groovy were given the values of some environment variables:
elasticSearch {
connection {
uri = env.ES_URL
username = env.ES_USER
password = env.ES_PASSWORD
}
indexPrefix = 'test-'
}
Since I never created the corresponding environment variables, the GrailsContextLoader fails to find the corresponding value and the computation fail.
Initializing the required environmnent variables in my IDE and running the tests as Grails tests solved the problem.
By your extends Specification seems that what you have there is a unit test. grailsApplication is not available on unit specs, though it can be mocked (ie. using the #TestFor(ClassUnderTest) annotation mockes it up for you).
If what you want to test is configuration I would recommend writing an integration spec. On the integration phase, you basically have a wired grails application without the web interface. In that case all you'll need would be to do is
package com.myCompany.routing.spring
import com.dropbox.core.DbxRequestConfig
import grails.util.Holders
import grails.test.spock.IntegrationSpec
class DropboxSpringConfigSpec extends IntegrationSpec {
def grailsApplication //This will be auto-wired
def "It instantiates and configures the dropboxRequestConfig component"() {
given:
def ctx = grailsApplication.mainContext
//do stuff...
}
}
Re that test having worked previously in your VCS. I've never used Holders on a unit spec, so I cannot really say it wouldn't work, but it may have just been a false positive. From my understanding on the unit phase you don't have a running grails application and beans (including config) would not be available until mocked by you or the testing framework (again, using #TestFor or #Mock)

Resources