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.
Related
I start my desktop app with a login, validate the user and "redirect" to the index Jframe.
What I want now is to store a user Object obtained from login so that it's available in all jframes that I'll use later.
Is it possible? I know that session variables are not that useful in desktop apps but I can't seem to find the way to create a static variable.
I tried creating my Object user in main, then setting it up after login. But it couldn't find the variable.
you can use a static variable:
public class MyAppContext {
public static volatile Object loginObject;
}
MyAppContext.loginObject = "whatever";
Or use a framework like Spring to manage your contexts.
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'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.
I have been wrestling with this problem for a while. I would like to use the same Stripes ActionBean for show and update actions. However, I have not been able to figure out how to do this in a clean way that allows reliable binding, validation, and verification of object ownership by the current user.
For example, lets say our action bean takes a postingId. The posting belongs to a user, which is logged in. We might have something like this:
#UrlBinding("/posting/{postingId}")
#RolesAllowed({ "USER" })
public class PostingActionBean extends BaseActionBean
Now, for the show action, we could define:
private int postingId; // assume the parameter in #UrlBinding above was renamed
private Posting posting;
And now use #After(stages = LifecycleStage.BindingAndValidation) to fetch the Posting. Our #After function can verify that the currently logged in user owns the posting. We must use #After, not #Before, because the postingId won't have been bound to the parameter before hand.
However, for an update function, you want to bind the Posting object to the Posting variable using #Before, not #After, so that the returned form entries get applied on top of the existing Posting object, instead of onto an empty stub.
A custom TypeConverter<T> would work well here, but because the session isn't available from the TypeConverter interface, its difficult to validate ownership of the object during binding.
The only solution I can see is to use two separate action beans, one for show, and one for update. If you do this however, the <stripes:form> tag and its downstream tags won't correctly populate the values of the form, because the beanclass or action tags must map back to the same ActionBean.
As far as I can see, the Stripes model only holds together when manipulating simple (none POJO) parameters. In any other case, you seem to run into a catch-22 of binding your object from your data store and overwriting it with updates sent from the client.
I've got to be missing something. What is the best practice from experienced Stripes users?
In my opinion, authorisation is orthogonal to object hydration. By this, I mean that you should separate the concerns of object hydration (in this case, using a postingId and turning it into a Posting) away from determining whether a user has authorisation to perform operations on that object (like show, update, delete, etc.,).
For object hydration, I use a TypeConverter<T>, and I hydrate the object without regard to the session user. Then inside my ActionBean I have a guard around the setter, thus...
public void setPosting(Posting posting) {
if (accessible(posting)) this.posting = posting;
}
where accessible(posting) looks something like this...
private boolean accessible(Posting posting) {
return authorisationChecker.isAuthorised(whoAmI(), posting);
}
Then your show() event method would look like this...
public Resolution show() {
if (posting == null) return NOT_FOUND;
return new ForwardResolution("/WEB-INF/jsp/posting.jsp");
}
Separately, when I use Stripes I often have multiple events (like "show", or "update") within the same Stripes ActionBean. For me it makes sense to group operations (verbs) around a related noun.
Using clean URLs, your ActionBean annotations would look like this...
#UrlBinding("/posting/{$event}/{posting}")
#RolesAllowed({ "USER" })
public class PostingActionBean extends BaseActionBean
...where {$event} is the name of your event method (i.e. "show" or "update"). Note that I am using {posting}, and not {postingId}.
For completeness, here is what your update() event method might look like...
public Resolution update() {
if (posting == null) throw new UnauthorisedAccessException();
postingService.saveOrUpdate(posting);
message("posting.save.confirmation");
return new RedirectResolution(PostingsAction.class);
}
Im trying to understand how the Passive View design pattern works for simple web apps.
Can someone provide a simple example of this pattern using these requirements:
View is a JSP that prints HELLO WORLD!
Data is persisted in the data store as "hello world", call to retrieve data can be a stub
Provide example files for pieces (presenter, view, etc) and denote which piece of the pattern each file represents.
No frameworks/DSLs should be used other than jstl/el (which are optional)
Thanks
UPDATE 1: Adding my understanding of how this would be structured.
// Presenter; responsible for multiple "rendtions" of a particular view (show, index, edit, summary, etc.)
public class HelloWorldPresenter {
private HttpServletRequest request;
private DataStore dateStore;
public HelloWorldPresenter(HttpServletRequest request) {
this.request = request;
this.dataStore = DataStoreUtil.getDataStore(request);
// Do a bunch of other inits that all getXXXModels() will use
}
public getShowModel() {
HelloWorldShowModel model = new HelloWorldShowModel();
String tmp = makeLoud(this.dataStore.getMyData()); // Stub method
model.setText(tmp);
return model;
}
private String makeLoud(String str) {
return str.toUpperCase() + "!";
}
}
// Model used by view
public class HelloWorldShowModel {
private String text;
public getText() { return this.text };
public setText(String text) { this.text = text; }
}
// View
show.jsp
<c:set var="model" value="new HelloWorldPresenter.getShowModel()"/>
${model.text} -> HELLO WORLD!
or
<% HelloWorldShowModel model = new HelloWorldPresenter(request).getShowModel() %>
<%= model.getText() %>
The things I'm unsure about are:
How the Presenter would be exposed to the View (JSP) since the View shouldnt know about the presenter. I may be mixing semantics though, and the HelloWorldShowModel (which is acting as a "ViewModel" of sorts, is what shouldnt know about the Presenter).
Should I even have the HelloViewShowModel abstraction, or should I simply have a method getText() on my Presenter which is called within the JSP to get the requested text.
If I do have multiple "views" for a resource (ex. Show, Index, Edit, Summary, etc.), should I have multiple Presenters? How should this logic be broken up? Multiple presenters that inherit from a Shared presenter? Should each presenter only be responsible for returning one ViewModel?
I've read through Fowlers articles as well as a number of other write-ups - the problem (for me) is they are written in the context of .NET apps, and I dont understand how all their objects get wired up.
I hope this will aleve concerns of me being "lazy" and looking for a "hand-out" answer :)
With the requirements you state I would say the pattern can't be implemented. If you consider the view to be a JSP then there are no means a controller could actively set any values of UI components. (To me this is the core of the pattern: the controller actually updates the view actively by setting values of input / output UI components, not the other way round (view getting fields from a model object). This can't be done with the above techniques as a JSP has no means to be accessesd this way.
It could be implemented in a web environment based on Javascript though. Consider your view being the DOM and your controller being a Javascript component. The JS controller has direct write access to the DOM and therefore could update single fields actively like the pattern suggests. To update / get the model the JS controller could talk to a server-side system e. g. based on a REST API via Ajax.
A plain templating solution like JSP cannot be used to offload all logic to controller, at least in real world cases. I think this kind of thing can be achieved with JSF.
If you want to learn about how things are done I recommend you to take a look at Spring MVC. It's source code can teach you a lot.