Could some explain me something. Here is some scenario.
Let assume i have a class template and use Gin/Guice in the app.
#Singleton
public class Template extends Compose
{
private HorizontalPanel header;
private HorizontalPanel content;
private VerticalPanel menu;
public Template()
{
this.add(initHeader());
this.add(initMenu());
this.add(initContent());
}
public void setContent(Widget widget)
{
content.clear();
content.add(widget);
}
.............
......
}
and in the entry class
........
public void onModuleLoad()
{
RootPanel.get().add(new Template());
....
}
Every time i need to reload the content i do..
For example
HorizontalPanel hp = new HorizontalPanel();
hp.add ....
...
Template template = injector.getTemplate(); // return singleton instance using gin
template.setContent(hp)
and so on..
So, Template is singleton and as far as i know singleton instance is one per VM meaning shared by entire application, right?
Template class has header, menu and content, the idea is to reload only the content part as cleaning and adding widgets.
But is this a good approach?
For example, could we have a situation like user "A" setContent(widgetA) ,but in the same time user "B" use method setContent(widgetB) ,so what is going to happen here?
Thanks, if anyone could share with me a good approach eventually and comment that one.
Regards
#Singleton is scoped to the Ginjector instance (yes, if you GWT.create() your GInjector twice, you'll get two "singletons"). There's no single mean GIN can somehow "intercept" your new Template() in onModuleLoad, so injector.getTemplate() will return a distinct template instance.
(this is totally different from the "singleton code anti-pattern" that Stein talks about, using static state)
There's no magic: GIN is a code generator, it only writes code that you could have typed by hand.
As for your other questions:
You client code obviously run on the client, i.e. on the browser. There's one "application instance" per browser tab/window displaying your app. There's no "user A" and "user B" at the same time.
JavaScript is single-threaded, so you don't have to fear for concurrent accesses either.
I have injected the class with common RPC code for our app.
Here's how:
#Singleton
public class SomeService {
/** The real service. */
private static final RealServiceAsync realService;
...
}
Our Gin module:
public class MyGinModule extends AbstractGinModule {
#Override
protected void configure() {
bind( SomeService .class ).in(Singleton.class);
...
...
}
}
And it's injected as singleton as follows:
public class ApplicationInfoPresenter {
#Inject
private SomeService service;
...
...
}
I'm pretty sure the annotation is ignored by the GWT compiler.
When I need a Singleton in gwt i just create a class with a private/protected constructor, and a private static NameOfSingletonClass instance; and a getInstance() method that initializes the instance if null and returns the instance.
Related
I try library cicerone.
The sample use MOXY.
I cant undestend why we should use #ProvidePresenter and #InjectPresenter in the same class, and dont use it anywhere.
#InjectPresenter
StartActivityPresenter presenter;
private Navigator navigator = new SupportAppNavigator(this, -1);
#ProvidePresenter
public StartActivityPresenter createStartActivityPresenter() {
return new StartActivityPresenter(router);
}
#InjectPresenter tells moxy, where should be placed Presenter. #ProvidePresenter tells how to create instance of this Presenter. Also, #ProvidePresenter will be called one time. But presenter field will be initialized after each activity restart.
My installer is storing some information in a singleton class during the installation process. Now, I have noticed that in elevated action, the singleton class does not have the same instance. So far, I have not found any workaround/solution so that they share the same instance. So, I have decided to make sure that if anyone wants to get an instance of the singleton, they must call from an unelevated environment. Let's say the singleton looks like the following:
public class InvestigatorReport {
private final List<Report> reports = new ArrayList<>();
private final static InvestigatorReport INSTANCE = new InvestigatorReport();
private InvestigatorReport() {
MyLogger.logInfo(getClass(), "initiating...");
}
public static InvestigatorReport getInstance(Context context) {
if (context.hasBeenElevated()) {
throw new IllegalAccessError(
"this method must be called unelevated!");
}
return INSTANCE;
}
private boolean addReport(Report report) {
return reports.add(report);
}
}
But the problem is, There are some cases when I have to call this add report from an action class that is elevated. So I have tried the following in my elevated action class:
if (context.hasBeenElevated()) {
return (Boolean) context.runUnelevated(new RemoteCallable() {
#Override
public Serializable execute() {
return getInstance(context).addReport(report);
}
});
}
But, as you can see if I am passing the same context object from the elevated action class to the RemoteCallable class so, even though I am running the class unelevated, the context.hasBeenElevated() still returns true.
Is there any other way that I can check the elevation level other than the context? If you have any other better idea on preventing anyone from calling the singleton getInstance() method, I am all ears.
I would use a different pattern. Make all methods of your singleton static and wrap the data access with runUnelevated calls:
public static boolean addReport(Report report, Context context) {
context.runUnelevated(new RemoteCallable() {
#Override
public Serializable execute() {
InvestigatorReport.reports.add(report);
return null;
}
});
}
In that way, you can call the methods from both elevated and unelevated code without having to check anything at the call site.
I am using Vaadin 7 with CDI. Everything worked perfectly until I wanted to use other UI class in my project for dynamic document generation.
#CDIUI(value = "PrintUI")
public static class PrintUI extends UI
{
#EJB
MyBean myBean;
#Override
protected void init(VaadinRequest request)
{
setContent(new Label(myBean.getHTMLContent(), ContentMode.HTML));
}
}
//method somewhere in the main UI class custom component
void printOpenedPage ()
{
// Create an opener extension
BrowserWindowOpener opener = new BrowserWindowOpener(PrintUI.class);
opener.setFeatures("height=200,width=400,resizable");
// A button to open the printer-friendly page.
Button print = new Button("Click to Print");
opener.extend(print);
}
My problem is that when I open the window I always get NPE because MyBean object in't injected. I tried to use #Inject and #EJB. Also tried to inject a local interface of the class, but no luck. Is it possible to access Stateless ejb objects in UI class that is opened trough BrowserWindowOpener class?
Thanks in advance
I am developping a server application in Java. I need to load some ressources from different sources (XML and a Database). So, i need some advice on how to cleanly implement the loading.
I have a class "ServerX" who create some "Memory" object, it's those objets who'll hold the loaded ressources.
I've found two different way of loading, but both seems dirty.
1
public class ServerX
{
/**
Will hold the houses for further use.
*/
private Memory<House> houses;
public ServerX()
{
houses = new Memory<House>();
loadHouses();
loadXX();
loadYY();
LoadZZ();
Load...
}
private void loadHouses()
{
//Pseudo code
List<House> loaded = loadHousesFromDatabase();
houses.addAll(loaded);
}
private void loadXX();
...
}
But this way, it flood my "ServerX" class.
2
public interface Loader
{
public void loadHouses(Memory<House> toFill);
public void loadXX(Memort<XX> toFill);
public void loadYY(Memort<YY> toFill);
public void loadZZ(Memort<ZZ> toFill);
}
public class SimpleLoader implements Loader
{
//Implements methods.
}
public class ServerX
{
/**
Will hold the houses for further use.
*/
private Memory<House> houses;
public ServerX(Loader loader)
{
houses = new Memory<House>();
loader.loadHouses(houses);
loader.loadXX...
}
}
But this way, i think i fall into the Poltergeist antipattern, because i create a new loader only to do the request to the database/XML file, and then it's garbage-collected.
So, is there another way to do it, or is one of my solutions good enough?
Thanks.
One pattern you can consider is the Service Locator Pattern. An explanation of Service Locator can be found here.
Basically, a service locator is a registry + cache combined to find the resource once and keep it in memory for object retrieval during the lifecycle of the application. Service Locator is mainly implemented using the Singleton pattern.
Your second solution using a Loader interface and multiple implementations (XMLLoader and DBLoader) is good. However, keep the loader and the server decoupled by making the load methods return a new Memory instance instead of passing the memory as a reference. Add a copyAll method in Memory class to copy the contents of one memory into another memory. ( See ArrayList.addAll or System.arrayCopy in javadoc )
I have a JTextArea always visible in my main app window (a Log if you like), and I want to use it to display activity going on in the system (like mock-debug output you'd do with System.out.println() in if conditions or whatever)
I mean high level things the user does, (like "successfully loaded file " or " written to disk", " completed" etc)
Thing is such messages can be generated anywhere in my system mainly in another package the classes of which deal with the data and computation, and they're unaware of the GUI.
Maybe save the messages to a temp file and the textarea "monitors" that file for changes, how can this be done?
The simplest way is to define a logger interface:
package com.example.logging;
public interface ActivityLogger {
void logAction(String message);
}
Then pass it to your non-GUI components so they don't get tied to a specific implementation:
public class FileLoader {
private ActivityLogger logger;
public FileLoader(ActivityLogger logger){
this.logger = logger;
}
public void loadFile(){
// load stuff from file
logger.logAction("File loaded successfully");
}
}
Now, making an implementation that writes to a text component is simple:
public class TextComponentLogger implements ActivityLogger{
private final JTextComponent target;
public TextComponentLogger(JTextComponent target) {
this.target = target;
}
public void logAction(final String message){
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
target.setText(String.format("%s%s%n",
target.getText(),
message));
}
});
}
}
// Usage:
JTextArea logView = new JTextArea();
TextComponentLogger logger = new TextComponentLogger(logView);
FileLoader fileLoader = new FileLoader(logger);
fileLoader.loadFile();
You can of course also use a standard logging framework (java.util.logging, slf4j, log4j, etc) and write an appender that "writes" to a text component.
The design can be rather complicated. Maybe you can have a public access method like updateText() in the class where your TextArea would be. Then you create a kind of 'resource' or 'shared' class (just a plain class) that would be initialized together when your main() runs. When the class containing your TextArea is created, an instance would be placed into the 'shared' class (this shared class should be a singleton) and so all the other classes call this 'shared' class (maybe a method like updateTextArea()) and what it would do is call the class containing the TextArea via that instance and call the TextArea to update text.
The Message Console might be what you are looking for.
Java also has a "Logger" API.
You can use EventBus to decouple your GUI from the other parts of your application. (My blog has another introduction). You could do something as follows:
public class LogArea extends JTextArea {
public static final String LOG_TOPIC = "logarea_topic";
public LogArea() {
super();
// Read in the annotations, register self as a listener to the topic
AnnotationProcessor.process(this);
}
#EventTopicSubscriber(topic=LOG_TOPIC)
public void logEvent(String topic, String text) {
append(text + "\n");
}
}
public class DomainClass {
public void foo() {
// Send out a notification throughout the system to whichever components
// are registered to handle this topic.
EventBus.publish(LogArea.LOG_TOPIC, "some text you want to appear in the log area");
}
}
In a real system you'd probably want to move the topic declarations to another class so that one can use it without being tied to a specific implementation. E.g. you could have a Topics class that just contains the static string constants of the topics. Then you can have multiple classes that listen to those topics and process the messages (e.g. you could have a standard logging framework which writes out to a log file in addition to the jtextarea component).