Accessing the Global object in play! 2.0 with Java - java

I have extended the GlobalSettings class as shown in the tutorial Application global settings.
How do I then gain access to the instance of this class, let's say from a view method?
I'm assuming that one instance was created when the application was started and that it is probably a member of some object.
I would have expected for example to find it here:
Play.application().getGlobalSettings()
or something similar, but I couldn't find it anywhere in the Play.* hierarchy.
Any ideas?
Thanks.

I'm new to Play 2.0, however, I think you're better served by using plugin injection. Check this out:
https://github.com/typesafehub/play-plugins/tree/master/inject
Using this approach you simply add the following line to your controller (and some other configuration, as documented in the link above):
#Inject static MyStaticObj obj;
And all the rest is done automatically using the injection framework. No need to worry about global, etc.
That said, like you I spent a lot of time trying to figure out how to use the GlobalSettings object for this before discovering the plugin injection framework.
My sense is that given how Global is implemented (as class in the default/unnamed package) it's not possible to reference it anywhere in the application code. I'm not sure if this was by design or by accident (it seems that the Play folks are thinking about Scala quite a bit these days...). Fortunately the plugin approach seems to be better way to handle these shared globals.

Just reference the Global object directly.
For example don't write :
public class Global extends GlobalSettings {}
write
object Global extends GlobalSettings {}
or
object Global extends Global {}
class Global extends GlobalSettings {}
and than you can reference Global object anywhere in your code just write :
Global.someMethod()

Related

Android: Passing same variable between 3 activities?

So I have a (Kotlin) data class that gets instantiated in my startup activity (we'll just call the object dataObj). I have two other activities that need access to the dataObj that was instantiated on startup. I know I could have my data class implement the Serializable interface so that I could pass the object between the three activities using intents. But I also have been thinking that I could use a static variable in the constructor so that I could easily just grab the values for the class. I'm just trying to figure out what is recommended and what is good practice.
It really depends on your use case, but I'd generally recommend against static implementations (to include singletons, see What is so bad about singletons?). They become hard to test adequately over time and can (in short) lead to many other problems depending on implementation.
If it is a relatively simple object where state change is rare, only done in one Activity at a time, and/or irrelevant, implementing a Parcelable and passing that to each Activity via an Intent is probably best.
If this is a complex object or an object that can change dynamically, the preferable solution would be to use a dependency injection platform (such as Koin if you're using Kotlin) to instantiate the data and provide it as a dependency. Koin is pretty straight forward, a very basic implementation from the Koin website (and missing just a few lines to be complete):
// Injected by constructor
class MyViewModel(val repo : MyRepository) : ViewModel()
// declared ViewModel using the viewModel keyword
val myModule : Module = module {
viewModel { MyViewModel(get()) }
single { MyRepository() }
}
// Just get it
class MyActivity() : AppCompatActivity() {
// lazy inject MyViewModel
val vm : MyViewModel by viewModel()
}
In this case, your object would be something like MyRepository() in the example. You'd just have to add the startKoin([list of modules]) from there. If you wanted MyRepository() in your Activity you'd include it like val myRepo: MyRepository by inject(). I don't know if this is outside the scope of your project though, it all depends on what you're trying to do exactly.
One big issue with this is that static variables don't survive Android low-memory state, but sending intent between survives. Also read here about static variable. (Link)
You have two options here:
Send it via Intent after implementing Serializable or Parcelable by you data class,
Save your data object to .txt file and read it when you need it.
static it is not created for this kind of things and You shouldn't use it in this case.
In my opinion You should go with first option.
This isn't the best method (although there really isn't a perfect way to do this), but you could instantiate it in a custom Application class.
class App : Application() {
val yourObject by lazy { YourObject() } //by lazy is useful if the Object needs to hold a Context or something that isn't immediately available
}
Add android:name=".App" to the application tag in your manifest so your App class is actually used. .App assumes it's in the root of your application package.
Then, from anywhere you have a reference to a Context, you can do something like:
(context.applicationContext as App).yourObject
to access the Object.

Multiple classes extending Application

two classes extend Application
One class I've registered in the Manifest and am using as an Application is meant to be
Second class is my utilities class. It does lots of I/O and has a few helper methods. For I/O you need context (getAssets etc), so I reluctantly extended Application.
Note:
Everything is working as it should.
My Question:
Are there any drawbacks of using multiple Application classes? Is this even advised?
A few thoughts:
Like what would happen if I had onCreate and other callback methods defined in both the classes?
How do I register them both in the manifest even?
etc
PS: I know I can just use a field to store context in the second class.
I think this is not advised at all, because there is could only be one instance on Application (thus only one class).
I am very suspicious about what is really working. You're talking about utility class, so maybe you're using static methods that are working well. But you should use your debugger, and I'm almost certain that you'll discover that one of your classes is never instantiated.
By the way, the official documentation states that :
" There is normally no need to subclass Application. In most situations, static singletons can provide the same functionality in a more modular way. If your singleton needs a global context (for example to register broadcast receivers), the function to retrieve it can be given a Context which internally uses Context.getApplicationContext() when first constructing the singleton. "

Create a class that is accessible to the whole application

In android there is a mechanism of ensuring that only one instance of a class is available to the whole application. This can be done by deriving that class from Application.
Can some thing similar be done in servlets? I want to initialize a class when the application is deployed. This class should have only one instance. So that what all the servlets can access it.
I came to know that you can store your data in the servlet context's hashmap. But I don't want to do that. I want to write my own class with its functions. How should this be done?
I think what you're after is simply a singleton.
This is best implemented by defining an enum with a single instance. (Note that enums allow you to have member functions just as classes.)
public enum YourSingleton {
INSTANCE;
// Your methods...
}
and then you access it as
YourSingleton.INSTANCE
So, create whatever class you want with its own functions or whatever you like, and put that in the ServletContext at startup. You can use a ServletContextListener to initialize and remove it. What's limiting about that?
Use singleton pattern so the first call to instance method (say YourClass.getInstance()) will create the instance and it will be reused across the application.

accessing static method across plugins

I have two plugins pluginA, and pluginB, which are using SDK from a platform C. Obviously pluginA and pluginB would not be able to access methods from each other, and any communication between pluginA and pluginB must be via C.
pluginA has a utility class utilA , which has a static method getMethod() which will be used in pluginB. and returns an object of a class which is also in pluginB itself. I can create any interface/factory class , in platform C, so that this communication can be done.
Can someone suggest how to tackle this problem.
This is a Factory design pattern. The factory should be a resource accessible from the SDK to all "plugins" and the SDK should decide (perhaps with a settings file or annotations) which plugin becomes the supplier for the factory.
One other design thought. I prefer to use interfaces as the output of a Factory object. That way one class can implement the interface any way it likes, and every other class (no matter when created, or how loaded by the ClassLoader) can use that factory. This may save you a bunch of headaches at testing or runtime.

Java VM Object references

I got a question: Is it possible to get a list of currently instantiated objects from the VM?
I am using a framework and try to implement an event handler (Hibernate, Interceptor). My problem now is that I need a Properties file during the execution of this handler. I cannot pass a reference to the Interceptor class, because Hibernate or the interface does not have such a method.
I now thought, why not trying to get the reference another way? Or is it possible to register global available objects during the runtime of an application?
Thanks for advice and regards from Germany,
Marco
I now thought, why not trying to get
the reference another way? Or is it
possible to register global available
objects during the runtime of an
application?
You can use a public static field. This belongs to the class rather than to any instance of the class. Very simple example:
public class Properties {
public static String PROPERTY = "abc";
}
You will then be able to access it from anywhere with:
Properties.PROPERTY
You can find more here:
http://java.sun.com/docs/books/tutorial/java/javaOO/classvars.html

Categories

Resources