In a Groovy script is it possible to do a conditional import statement?
if (test){
import this.package.class
} else {
import that.package.class
}
The background to this is wanting to use something on MacOS 10.5 which only has JDK1.5 so one specific class is unavailable, but I have found someone who has written a back-port for it.
There is no way to conditionally import a class, but you can achieve something similar by attempting to load the class and then load another class if that one is not found.
Here's just an example:
def someClass
try {
someClass = "org.apache.webdavlib.WebdavFile" as Class
} catch (Exception ex) {
someClass = "java.io.File" as Class
}
def someInstance = someClass.newInstance("~/project/temp.log")
assert "java.io.File" == someInstance.getClass().getName()
Jochen "blackdrag" Theodorou proposed the following on the groovy user list a while ago:
wsh = this.class.classLoader.loadClass("org.codehaus.groovy.scriptom.ActiveXObject").newInstance("WScript.Shell")
Then you do not need to use the import statement.
Here is the thread on the mailing list
No, conditional imports are not supported... Best I can think of atm would be to use reflection as you would need to in java...
An ast transform could also be used here to tag the class and wrap the code that uses the missing class with the required reflection code
I guess a class loader could do the trick, but will be complicated.
Have you considered to use a shadow class and jsut deploy different jars?
Something like
//jdk 1.5
somethingelse extends this {
}
.
//jdk 1.6
somtheingelse extends that {
}
=> compile both to two different jar files, which you deploy on one system but not the other...
not perfect, but could work
...wait: if your libraries just differ in the package name, then you don't need a shadow class. Can't you move the one or the other in the same package?
Related
According to Groovy doc, Example 40.2, a new class for a task should be created so (simply copy that to the build.gradle):
task hello(type: GreetingTask)
class GreetingTask extends DefaultTask {
#TaskAction
def greet() {
println 'hello from GreetingTask'
}
}
But if you really try to do it, the class declaration is marked as an erroneous because no abstract methods are written. About ten of them should be here... Is it really impossible to do a task class in a cheap way as in documentation? What is the problem with documentation? Or rather with some settings on my IntelliJ?
You are using the wrong DefaultTask class. The one from Gradle is not abstract.
When I create the mentioned task in the empty Gradle/Groovy project, no errors is shown.
In the context of my project, the error IS shown. But the task runs OK! It again seems as some hallucination of IntelliJ.
So I am trying to migrate a PlayFramework application from version 2.4.3 to 2.5.6. I am using Squeryl and akka-quartz-scheduler, and Squeryl requires setting up a session manually and akka-quartz-scheduler runs as its own entity, as none of the other modules really depend on it, though it will depend on others. So previously there has been a Global-object to handle them on start up:
import org.squeryl.{Session, SessionFactory}
object Global extends GlobalSettings {
private lazy val injector = Guice.createInjector(CustomModule)
override def onStart(app: Application) {
SessionFactory.concreteFactory = // Squeryl initialization http://squeryl.org/sessions-and-tx.html
injector.getInstance(classOf[CustomScheduler]).initialize()
}
}
This has worked before. However, on 2.5.6 I'm trying to shift away from Global.scala altogether. I'm not sure if this is the best way to do this, but from documentation it seems like it. So I'm trying to create Singleton classes, and load them eagerly before the application loads like instructed here as a replacement for onStart. So like instructed on eager bindings -page I have:
import com.google.inject._
class CustomModule extends AbstractModule {
override def configure() = { // or without override
println("configure called")
bind(classOf[SquerylInitialization]).to(classOf[SquerylInitialization]).asEagerSingleton()
bind(classOf[CustomScheduler]).to(classOf[CustomScheduler]).asEagerSingleton()
}
}
import play.api.{Configuration, Application}
import play.api.db.{DB, DBApi}
import org.squeryl.{SessionFactory, Session}
#Singleton
class SquerylInitialization #Inject()(conf: Configuration, dbApi: DBApi) extends Logging {
SessionFactory.concreteFactory = // Squeryl initialization http://squeryl.org/sessions-and-tx.html
}
import akka.actor.{ActorSystem, ActorRef}
#Singleton
class CustomScheduler #Inject()(system: ActorSystem) extends Logging {
val scheduler: QuartzSchedulerExtension = QuartzSchedulerExtension(system)
// other initialize code here
}
The CustomModule inheriting the AbstractModule and its configure()-method is never called. It is said in Guice documentation that "Alternatively, play will scan the classpath for classes that implement AbstractModule". Documentation might not be the most recent, but that seems to be the way it works.
If for instance on all classes using Squeryl I use dependency injection to load SquerylInitialization it works, but I'm not sure if that's good way to do it as it would have to be required by tons of Classes, and there is hardly any Class depending on the CustomScheduler.
So basically the questions are:
Why isn't the CustomModule calling the configure()-method and eager
loading the Classes, and how that should be fixed?
Is this the standard way to load this kind of functionality, or should some other way used?
So basically comments are correct and the documentation was just out of date, so including
play.modules.enabled += "module.CustomModule"
helped. Thought I tried that as well, but turns out I didn't. Answer just a comment so can't accept that.
I used to get the application.conf variable in Play 2.4.x with Play.current.configuration.getString('NAME_HERE'), and it was working good in class, object and companion object too.
Now, I'm using Play 2.5.4 with Scala in a new project, and I won't use this Play.current, because it's deprecated, but there is an alternative using DI, like this :
class HomeController #Inject() (configuration: play.api.Configuration) extends Controller {
def config = Action {
Ok(configuration.underlying.getString("db.driver"))
}
}
This DI Injection works like a charm in class, but in this project, I need to get the variable db.driver in a object? And as far I know, with an object I can't use DI.
Maybe using Guice would help?
You can use #Singleton annotated class instead of object
trait Foo {}
#Singleton
class FooImpl #Inject()(configuration: play.api.Configuration)) extends Foo {
//do whatever you want
}
#Singleton makes the class singleton.It feels bit awkward because Scala itself natively have syntax object to create a singleton, But this is the easiest and probably best solution to DI into a singleton.
You also may create the singleton eagerly like the code below.
bind(classOf[Foo]).to(classOf[FooImpl])asEagerSingleton()
for more detail Info, You can look up Google Guice Wiki and Playframework site
EDIT
How you call it is exactly the same as how you DI in Playframework2.5.
class BarController #Inject()(foo: Foo) extends Controller {
//Do whatever you want with Foo
}
Guice basically generates new instance every time you DI, Once you put #Singleton, Guice use only one instance instead.
DI is for anti-high coupling.So when you want to use a class you defined from another class,You need to DI otherwise the classes are highly coupled which end up making it harder to code your unit test.
FYI, You can use them outside of Play with this technique.
Create an Instance of class which does DI via Playframework Guice Independently in Scala
Have you tried
import com.typesafe.config.ConfigFactory
val myConfig = ConfigFactory.load().getString("myConfig.key")
Above approach doesn't require you to convert your object to singleton class.
You can do
Play.current.configuration
however that will (probably) no longer be possible with Play 2.6.
Ideally, however, you would pass the configuration in as a parameter to that method of the object or, use a class instead of an object.
What I somtimes do to migrate 'from object to class':
class MyComponent #Inject() (config: Configuration) {
// here goes everything nice
def doStuff = ???
}
object MyComponent {
#deprecated("Inject MyComponent")
def doStuff = {
val instance = Play.current.injector.instanceOf[MyComponent]
instance.doStuff
}
}
This way, you're not breaking existing code while all users of your methods can slowly migrate to using classes.
The following unexpectedly compiled and ran without a problem:
import info.gridworld.actor.Actor;
import java.util.ArrayList;
public class ChameleonKid extends ChameleonCritter
{
public ArrayList<Actor> getActors()
{
ArrayList<Actor> actors = getGrid().getNeighbors(getLocation());
ArrayList<Actor> frontBack = new ArrayList<Actor>();
for(Actor i : actors)
if(getLocation().getDirectionToward(i.getLocation())==getDirection())
frontBack.add(i);
return frontBack;
}
}
The method getLocation() in the Actor class returns an instance of Location. And then I call the getDirectionToward() method of the Location class. getLocation().getDirectionToward(i.getLocation()). How does this work? I never imported the Location class. How am I able to work with it and call its methods? If that is how it works, when would I need to import a class? Only if I am instantiating it?
I am using Java 7.
Say you have two methods, one returning foo.Location and the other returning bar.Location (two completely different classes happening to have the same name, but in different packages - completely valid):
foo.Location getFooLocation();
bar.Location getBarLocation();
When you can both of these methods in the same class and chain some methods, you don't need an import:
if(getFooLocation().onlyInFoo()) {
//...
}
if(getBarLocation().onlyInBar()) {
//...
}
It works because the compiler is completely sure which version (from which package) of Location are you using and it knows where onlyInFoo() and onlyInBar are available.
But suppose you need a local variable:
Location location;
// much later
location = getFooLocation();
Now the compiler doesn't really know Location do you mean, so you must help him either by proceeding class name with package:
foo.Location location;
or by importing that class:
import foo.Location;
You should now ask: what if I want to have local variable of both foo.Location and bar.Location? Well, you can't import them both, obviously:
//WRONG
import foo.Location;
import bar.Location;
What you can do is again: either don't import at all and use fully qualified names:
foo.Location location1;
bar.Location location;
...or import just one location:
import foo.Location;
//...
Location location1; //foo.Location
bar.Location location2;
The reason why you don't need to import that class is because of the fact that you are not explicitly using that class. Actor is the one actually using the Location class locally. You are never holding a reference to the Location class and so, you are able to keep using it dynamically. However, if you wanted to hold a reference (eg Location l = getLocation();), you would have to import Location since the compiler has to link l with Location, but has no idea where to find it.
Enumeration code looks like the following
package com.mydomain
object Market extends Enumeration {
type Market = Value
val ASX, LSE = Value
}
I try to use as follows
import com.mydomain.Market._
.
.
.
if (Market.ASX == currentMarket) {
...
}
This was working when everything was in the same package. When I moved to a new package I now get
not found: value Market
If you import Market, you have ASX and LSE directly available to you. You don't have Market.ASX available--that would be if you had object Market available, which is what would happen if you did import com.mydomain._.
Being inside package com.mydomain causes com.mydomain._ to be loaded just like you imported it, so that's why you can say Market.ASX when you're in the same package.
When you write code in a different package, you need to either import com.mydomain._ and then use Market.ASX, or import com.mydomain.Market._ and then use ASX.