I'm trying to set up a page view when a certain form is shown, and this is a GUI builder project. I initialized the AnalyticsService with the Google Analytics ID and my app name in the initVars method, and then when I want to fire a page view I used the AnalyticsService.visit(page name, referer). When I view the Google analytics data, is always shows no page info.
What needs to be done to get page view information sent to Google Analytics? Am I calling the visit method incorrectly?
Here's the initialization:
public StateMachine(String resFile) {
super(resFile);
// do not modify, write code in initVars and initialize class members
// there,
// the constructor might be invoked too late due to race conditions that
// might occur
}
/**
* this method should be used to initialize variables instead of the
* constructor/class scope to avoid race conditions
*/
protected void initVars(Resources res) {
Display.getInstance().lockOrientation(true);
AnalyticsService.init("(my Analytics ID)",
"rpcontrol.fastlaneinnovations.com");
AnalyticsService.setAppsMode(true);
AnalyticsService.setFailSilently(false):
....bunch more stuff}
And then elsewhere I try to trigger a page view:
#Override
protected void beforeDataLogs(Form f) {
logsContainer = findLogsContainer(f);
updateLogList();
AnalyticsService.visit("Logs", "");
}
It seems that the AnalyticsService class has two modes and if you created a mobile apps analytics you need to enable the apps mode using
setAppsMode.
This is probably better than the default behavior of using the old mobile website approach, unfortunately I don't think we can flip the default as this would break existing applications that might rely on this API.
Related
Wicket throws StalePageException only if some Ajax action has been performed on a page before duplicating the page.
Example wicket project can be found at, along with steps to reproduce the exception.
https://github.com/rjngshn/java-wicket-testing/tree/main
Is there a way to ensure this exception is not thrown?
Thanks
Rajani
The default behavior provided in Wicket is too queue AJAX requests as they come in. Let’s say you have a button with a callback that does some work when clicked and updates the UI. This means that if the button is quickly clicked three times successively, the last two requests will be queued up and processed after the first request finishes.
A simple solution is to change the behavior of the AjaxChannel from queueing to active. This means that if any AJAX requests are received while there is an active(unfinished) request being processed, they will be ignored.
So how do we override Wicket’s default behavior in one spot and ensure all AjaxChannel‘s are modified? We use a custom AjaxRequestTarget.IListener.
public class ActiveAjaxListener implements AjaxRequestTarget.IListener {
private static final AjaxChannel ACTIVE_CHANNEL = new AjaxChannel(AjaxChannel.DEFAULT_NAME, AjaxChannel.Type.ACTIVE);
#Override
public void updateAjaxAttributes(AbstractDefaultAjaxBehavior behavior, AjaxRequestAttributes attributes) {
attributes.setChannel(ACTIVE_CHANNEL);
}
}
Our ActiveAjaxListener class will modify every AJAX behavior and make sure it uses the active channel. To register it, we simple insert this line into our WebApplication init() method:
getAjaxRequestTargetListeners().add(new ActiveAjaxListener());
(I've copied this explanation from https://www.coderdreams.com/wicket-quick-tip-4-change-default-ajaxchannel-to-active/)
Another way is to use a veil that prevents the double clicks via JS/CSS. More details about this approach could be found at JavaScript / Wicket : How to display an overlay which prevents user interaction
I'm creating a web app.
I have a MyUI that extends UI.
public class MyUI extends UI {
public static Authentication AUTH;
#Override
protected void init(VaadinRequest vaadinRequest) {
AUTH = new Authentication();
updateContent();
}
//other methods
}
In Authentication() I have the user logged. When I do the logout, that user is set to null.
I noticed that when I access to the server from two device, so when I should have two connection to the server, when someone do the logout, the other one is logged out too.
In Authentication class there is this method:
public void doLogout() {
System.out.println("User: " + this.user.getMail() + " has logged out.");
this.user = null;
}
I get error in user.getMail() because the user is already set to null, when I try to do the logout from the other account.
Is com.vaadin.ui.UI unique? How can I handle different connections in Vaadin?
Java, in general
Basic Java here, nothing to do with Vaadin…
The keyword static means one value per class, otherwise known as a “class variable”, more generally known as a “global variable”. Not object-oriented. Generally speaking, you should minimize your use of static.
Omitting that keyword means “one value per instance of this class”, an instance variable also known as member variables. This is object-oriented.
I suggest you learn more of the basics of Java before embarking on a Vaadin project. And learn the basics of how Java Servlet technology works, perhaps reading the Head First book on Servlet published by O’Reilly (now outdated, but basics are the same). You also need to learn about advanced topics such as threading and concurrency issues as a Servlet environment such as Vaadin is inherently multi-threaded. Eventually, read the book Java Concurrency In Practice by Goetz.
Vaadin specifically
To store values per user of a Vaadin app, use session attributes. This is a key-value store where you insert and retrieve a value by specifying a key, the name of the "attribute". The session is automatically instantiated for you when the user first connects, as part of the Java Servlet technology.
Alternatively, you can store values per user on that UI class as instance variables. Each Vaadin user starts with a UI instance when first connecting. But beware: you can open multiple web browser tabs/windows in a Vaadin 8 app, each having their own UI instance. So to share data between those multiple UI objects, use the session attributes.
Note that while every Vaadin app has at least one UI subclass defined, you can define additional UI subclasses as well, for those additional browser tabs/windows mentioned above to show different content.
Maybe instead of static variable you should use here session attribute (updated to be more generic):
UI.getCurrent().getSession().setAttribute("AUTH", AUTH);
Authentication auth2 = UI.getCurrent().getSession().getAttribute("AUTH");
So use VaadinSession to store session specific data.
I have a login page and the main page. After login, I have
public void onSuccess(String result) {
// go to the next page
SDM_Mailer page = new SDM_Mailer();
RootPanel.get().remove(0);
RootPanel.get().add(page);
}
However RootPanel does not accept an EntryPoint object! add() only accepts a Widget! Ok, so I extend Widget
public class SDM_Mailer extends Widget implements EntryPoint {
But now when I try to edit SDM_Mailer in the GWT Designer, it gives this error:
So exactly how do you create multiple pages, that are not all in the same giant class file or using tab? I know I've done this before but don't remember and with an older version.
You can adopt Activities and Places.
As mentioned to the official gwt project site:
The Activities and Places framework allows you to create bookmarkable URLs within your application, thus allowing the browser's back button and bookmarks to work as users expect.
Activity
An activity simply represents something the user is doing. An Activity contains no Widgets or UI code.
Place
A place is a Java object representing a particular state of the UI. A Place can be converted to and from a URL history token
Source: http://www.gwtproject.org/doc/latest/DevGuideMvpActivitiesAndPlaces.html
You usually only have one EntryPoint from there you add different widgets (which can represent your different pages) and manage them.
A very simple way to do this is for a small app can be to use .setVisible(true) and setVisible(false) on different widgets that represent pages, but this is not a good method in the long run.
You could also have a container widget in which you add whatever widget you want to display and then when you want to put a new widget in it you clear it.
container.clear();
container.add(widget)
The suggestions above are ok for small apps but aren't great when your app has a lot of pages (views). A popular way to manage pages (views) is to use MVP Activities and Places. It's a lot of overhead but is scalable and works well.
Extending Widget doesn't magically make something representable in HTML. Widgets provide graphical representations of something in HTML, that is, a way to render themselves into HTML, this is ussualy achieved by implementing UIBinders. I strongly suggest you take the MVP approach and use Activities, Places and Views. check the official documentation on how to do it, it's simpler than you may think.
If you are working with Eclipse, the GWT plugin does most of the boilerplate. You can watch this video on how to use it.
This is what I ended up doing:
package com.example.client;
import java.util.logging.Logger;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.ui.RootPanel;
public class Controller implements EntryPoint {
private static Controller instance;
private static final Logger log = Logger.getLogger(Controller.class.getName());
// I have a feeling GWT does not respect private constructors, or else it uses some other voodoo.
private Controller(){}
public static Controller getInstance() {
if (instance == null) instance = new Controller();
return instance;
}
#Override
public void onModuleLoad() {
String token = History.getToken();
log.info("****************************** token:"+token);
History.addValueChangeHandler(new ValueChangeHandler<String>() {
#Override
public void onValueChange(ValueChangeEvent<String> event) {
navigate(event.getValue());
} // onValueChange
});
if (token == null || token.length() == 0) History.newItem(Login.TOKEN); // no token
else navigate(token); // restore app state
}
private static void navigate(String token) {
RootPanel rootPanel = RootPanel.get("gwtApp");
if (rootPanel.getWidgetCount() > 0) rootPanel.remove(0); // clear the page
if (Login.TOKEN.equals(token)) {
Login page = Login.getInstance();
page.onModuleLoad();
} else if (MainApp.TOKEN.equals(token)) {
MainApp page = MainApp.getInstance();
page.onModuleLoad(); // display the page
// page.setAuthenticated(true);
// page.setUsername(email);
}
}
} // Controller
In your *.gwt.xml file:
<entry-point class='com.example.client.Controller' />
Now when you want to go to a new page:
History.newItem(Login.TOKEN);
This seems quite familiar and is probably what I came up with a few years ago.
It is sometimes desirable to share context variables with all views, such as the current user or navigational state. Looking through the documentation, I haven't been able to find a way to share such global context variables accessible to the template engine in all views.
Is this provided by the framework, or am I better off explicitly passing these variables to all views, perhaps by writing a wrapper method called in all controllers whose views need these global variables?
You can use for that Session and Flash scopes
public static Result index() {
// session is good for storing session data such as for an example logged user's info
session("username", "John Doe");
// flash is available only for next request (in this case for view rendering process)
flash("navId", "mainPage");
return ok(index.render("ellou' World"));
}
index.scala.html
#(message: String)
#main(message) {
#if(flash.get("navId")=="mainPage"){<h1>Great! You're on main page again</h1>}
<div>You're logged as #session.get("username")</div>
}
of course for data which are individual for each page (like sample navId) you can also pass it to the view, where you can declare required type other than String.
I am using chrriis.dj.nativeswing.swtimpl.components.JWebBrowser in my swing application to open web page.
The page is going to show "Facebook Authentication" page and I want to prevent user from inputting some other URL other than I specify and also Forward and Back buttons should be visible but not has no affect.
So following functions are applicable for my goal
setButtonBarVisible(false);
setLocationBarVisible(false);
Once user completes the authentication I will handle the locationChanged event.
#Override
public void locationChanged(WebBrowserNavigationEvent arg0) {
System.out.println("locationChanged!");
....
}
}
I think what you want is a custom decorator. Check the demo application, under "JWebBrowser > Custom Decorator".
In your case, you could create a new decorator class, as an adapted copy of DefaultWebBrowserDecorator or a subclass with appropriate override.
You would also have to decide if this decorator is to be used only by one instance of the JWebBrowser or all instances (like child popups, etc.)