EJB's is not injected in Vaadin BrowserOepener window UI - java

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

Related

Serializing only works when called in static main method of JavaFX App class

I'm working on a project that uses JavaFX for the GUI (I know, non-serializable). I want to serialize objects such as my Users.
I'm not able to access the instance that JavaFX Application uses, but I have it associated in other classes.
For example - it is associated with my Controller class:
public class MyApp extends Application {
public void start(Stage stage){
// ... assume controller loaded
controller.setApp(this);
}
}
public class Controller {
MyApp app;
public setApp(MyApp app){
this.app = app
}
}
Now when I go to serialize an instance of MyApp, I'm having difficulty. I found a slight trick (option 1), but it feels a little messy. I'd much rather do option 2.
Option 1 [WORKS] - create an additional instance in the main method.
public class MyApp extends Application {
public void start(Stage stage){
// ... assume controller loaded
controller.setApp(this);
}
public static void main(String[] args){
MyApp app = new MyApp(); // this is a different instance than javafx instance.
launch(args)
app.users = Controller.getUsers();
writeApp(app);
}
public static void writeApp(PhotoApp photoApp) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new
FileOutputStream(storeDir + File.separator + storeFile));
oos.writeObject(photoApp);
oos.close();
}
}
Thus, option 1 essentially creates a new instance and copies stuff back and forth from the actual instance in controller.
OPTION 2 [DOES NOT WORK] - serialize the instance associated with the controller (since that is the actual instance JavaFX is using)
public class Controller {
MyApp app;
public void setApp(MyApp app){
this.app = app
}
public void someAction(){
MyApp.writeApp(this.app);
}
}
When I do Option 2 I get errors saying Controller is not serializable. I understand that it is not (which is okay), but I don't get that error in Option 1. In both options I'm calling the same method with some instance of MyApp. I'm not sure why it works for Option 1 but not Option 2.
Any reason why one option works over the other? How do most people do serialization of some of their objects when they use JavaFX?

create new java class in spring application

this is my first spring application (maven project) which is supposed to allow users to upload and validate a file. At the moment I only have the default class called MyUI.java which contains all I need, here is an extract:
EDITED CODE:
FileUploader.java
public class FileUploader extends AbstractJavaScriptComponent {
public void callScript(){//as usual, it needs a method!!
JavaScript.getCurrent().execute(""
+"jsInit();"
+"");
}
And changes to the MyUI class:
`final FileUploader fileUploader = new FileUploader();//has to be final apparently
final Button button = new Button("Open popup");
button.addClickListener(new Button.ClickListener(){
#Override
public void buttonClick(ClickEvent event){
fileUploader.callScript();
}
});`
I need to move the js call to a new java class in a separate file, so I created a new class which now sits in its own file and that will extend AbstractJavaScriptComponent, my question is, what imports do I need for this class, all the ones that are in the previous class except for the UI or including those? Literally this class will only have the js call for now (there will be more stuff later)?
Also, to make use of this class presumably I will have to run As --> maven install again? And in general, what should I do?
cheers
This is a simple case of refactoring to extract a method and add a class.
You want to replace this
final Button button = new Button("Open popup");
JavaScript.getCurrent().execute("jsInit();");
With something like this
final Button button = new Button("Open popup");
JavaScriptCaller jsCaller = new JavaScriptCaller(JavaScript.getCurrent());
jsCaller.jsInit();
So, you can define a class like so
public class JavaScriptCaller extends AbstractJavaScriptComponent {
final JavaScript js;
public JavaScriptCaller(JavaScript js) {
this.js = js;
}
public void jsInit() {
this.js.execute("jsInit();")
}
}
The reason I added the parameter is so you don't need to keep calling the Javascript.getCurrent() since you only need one instance of it.

Load Eclipse RCP 4 default perspective programmatically

I am creating eclipse RCP 4.x application. Application consist of multiple perspectives. I want to open default perspective programmatically depending on some condition. Below code is capable of loading perspective.
#Execute
public void execute(MApplication app, EPartService partService,
EModelService modelService) {
MPerspective element =
(MPerspective) modelService.find("com.sanyotechnologyindia.desktop.app.perspective.enduser", app);
// now switch perspective
partService.switchPerspective(element);
}
But I can not put this code in method which is annotated with #PostContextCreate.
Can you suggest any solution for this?
================
As per solution suggested by Greg, I tried following code in Application Lifecycle class.
#ProcessAdditions
void processAdditions(MApplication app, EPartService partService,
EModelService modelService){
MPerspective element =
(MPerspective) modelService.find("com.sanyotechnologyindia.desktop.app.perspective.usermanagement", app);
// now switch perspective
partService.switchPerspective(element);
}
Now I am getting following error at line partService.switchPerspective(element);
java.lang.IllegalStateException: Application does not have an active window
================Update:==================
Added org.eclipse.osgi.services plugin to dependencies.
#PostContextCreate
public void postContextContext(IEventBroker eventBroker)
{
eventBroker.subscribe(UIEvents.UILifeCycle.APP_STARTUP_COMPLETE,
new AppStartupCompleteEventHandler());
}
private class AppStartupCompleteEventHandler implements EventHandler
{
#Inject private MApplication app;
#Inject private EPartService partService;
#Inject private EModelService modelService;
#Override
public void handleEvent(Event arg0) {
MPerspective element =
(MPerspective) modelService.find("com.sanyotechnologyindia.desktop.app.perspective.usermanagement", app);
partService.switchPerspective(element);
}
}
However now framework not able to inject MApplication,EPartService and EModelService in AppStartupCompleteEventHandler instance.
If you only want to do this in your life cycle class try putting it in a #ProcessAdditions method rather than #PostContextCreate. #ProcessAdditions runs later in the life cycle just before the model is rendered.
Update:
Even #PostAdditions is too early to do some UI operations. You need to wait for the application start complete event. You can subscribe to this event using the event broker in the #PostContextCreate method:
#PostContextCreate
public void postContextContext(IEventBroker eventBroker)
{
eventBroker.subscribe(UIEvents.UILifeCycle.APP_STARTUP_COMPLETE,
new AppStartupCompleteEventHandler());
}
private class AppStartupCompleteEventHandler implements EventHandler
{
#Override
public void handleEvent(final Event event)
{
// TODO do UI operations here
}
}
EventHandler is org.osgi.service.event.EventHandler.
Update:
If you want to use injection in the event handler you must create the handler using `ContextInjectionFactory':
EventHandler handler = ContextInjectionFactory.make(AppStartupCompleteEventHandler.class, context);
where context is the IEclipseContext.
Note: You can't use this for a non-static inner class, instead use:
EventHandler handler = new AppStartupCompleteEventHandler();
ContextInjectionFactory.inject(handler, context);
This method does not support injection on the constructor.

Google guava singleton Eventbus fires multiple times

I use vaadin + spring IOC + google guava eventbus. Resources recommends to use guava eventbus as singleton. But when I do that I have the following problem;
Let's say I run the application on 3 different browsers at the same time, so I have 3 different instances of my application.
then for example when an I press a button on one browser and fire an event, I notice that my related listener method with the #subscribe annotation gets called 3 times!
Is this is a normal behaviour I would expect because I use eventbus as singleton? If not what is going on here? MainController is a spring managed bean with a a custom Vaadin Application Scope
class MainController{
public MainController() throws DAOException, Exception {
EventBusFactory.getEventBusInstance().register(this);
}
#Subscribe
public void addFacetEvent(FacetAddedEvent event) throws DAOException {
getTreeTableView().addToList(event.getData());
}
}
class EventBusFactory{
public static EventBus getEventBusInstance() {
if(eventBus==null){
eventBus=new EventBus();
}
return eventBus;
}
}
P.s I also hesitate in Vaadin should I to use guava eventbus or guava gwt event bus?
Thanks
Short answer: It's normal and expected behaviour in this configuration (you have three Vaadin Applications and hence three MainController instances managed with single EventBus).
By custom Vaadin Application Scope did you mean scope from this Vaadin addon?
Anyway, it's simple to reproduce your situation having prototype-scoped MainController bean and Vaadin App like this:
public class SandpitApplication extends Application {
private static final long serialVersionUID = 1L;
private static final Logger log = Logger.getLogger(SandpitApplication.class);
// https://vaadin.com/wiki/-/wiki/Main/Spring%20Integration#section-Spring+Integration-SpringContextHelperClass
private SpringContextHelper ctx;
#Override
public void init() {
// vaadin stuff
setTheme("common");
final Window mainWindow = new Window("Vaadin Sample Application");
setMainWindow(mainWindow);
// get your bean from spring
log.info("start SandpitApplication#" + Integer.toHexString(hashCode()));
ctx = new SpringContextHelper(this);
// create application-wide bean
final MainController mainController = ctx.getBean("mainController");
mainWindow.addComponent(new Button("click to post", new Button.ClickListener() {
#Override public void buttonClick(final ClickEvent event) {
log.info("click on button");
EventBusFactory.getEventBusInstance().post(
new FacetAddedEventImpl("click-"
+ new SimpleDateFormat("HH:mm:ss").format(new Date())));
log.info(mainController);
}
}));
}
}
and MainController class:
class MainController {
private static final Logger log = Logger.getLogger(MainController.class);
public MainController() {
log.info("creating MainController#" + Integer.toHexString(hashCode()));
EventBusFactory.getEventBusInstance().register(this);
}
#Subscribe
public void addFacetEvent(final FacetAddedEvent event) {
final String signature = "MC#" + Integer.toHexString(hashCode()) + ": ";
log.info("addFacetEvent in " + signature + event);
// getTreeTableViewBuilder returns extended ArrayList with fancy add
getTreeTableViewBuilder().addFacetToList(signature + event.getData());
}
// plus other stuff like toString etc.
}
When you do the following:
Start the vaadin app in your browser (App#1).
Click the App1#button.
Start another app (App#2).
Click the App2#button
Go back to tab with App#1.
Click the App1#button.
you'll get the following output:
start SandpitApplication#75a5555a
creating MainController#2e98f864
click on button // #1
addFacetEvent in MC#2e98f864: FacetAddedEventImpl#6b527dc6{data: click-13:42:45}
MainController#2e98f864{treeTableViewBuilder: [MC#2e98f864: click-13:42:45]}
start SandpitApplication#3f9e529
creating MainController#2f8d604f
click on button // #2
addFacetEvent in MC#2e98f864: FacetAddedEventImpl#36c1fc67{data: click-13:42:47}
addFacetEvent in MC#2f8d604f: FacetAddedEventImpl#36c1fc67{data: click-13:42:47}
MainController#2f8d604f{treeTableViewBuilder: [MC#2f8d604f: click-13:42:47]}
click on button // #1
addFacetEvent in MC#2e98f864: FacetAddedEventImpl#42d32028{data: click-13:42:49}
addFacetEvent in MC#2f8d604f: FacetAddedEventImpl#42d32028{data: click-13:42:49}
MainController#2e98f864{treeTableViewBuilder: [MC#2e98f864: click-13:42:45, MC#2e98f864: click-13:42:47, MC#2e98f864: click-13:42:49]}
You should now see that singleton EventBus is managing two application-wide MainController beans and each is recieving event (because it's resolved by global EventBus).
Trying to guess what do you want to achieve, I'd say that you need create application-wide event bus bean:
<bean id="eventBus" class="com.google.common.eventbus.EventBus"
scope="vaadinApplication" />
About P.S.: We use standard Guava in our Vaadin project extensively, no need for GWT version.

Singleton in GWT project

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.

Categories