GWT - Trouble with History first token - gwt

I have this problem : when i call the Content class (the one who decide which page to view, due to the #param) I do somethings like this :
History.addValueChangeHandler(this);
if(!History.getToken().isEmpty()){
changePage(History.getToken());
} else {
History.newItem("homepage");
}
So, now, if i look at browser's navigation bar, i see http://localhost:8084/GWT/?gwt.codesvr=127.0.0.1:9997#homepage. And that's right. Unfortunatly, If i press Back on my browser, i see that it load the previous address, such as http://localhost:8084/GWT/?gwt.codesvr=127.0.0.1:9997
I have a sort of "fake" page at the beginning.
1 - How can I fix it? And start the application with a default token, or remove it in the history. Or just call the onValueChange method when there is empty token, and after decide the workflow with a sort of switch/if-else.
2 - As related question, when i call History.addValueChangeHandler(this); in the costructor class, netbeans say "Leaking this in constructor". What it means?
Cheers

Maybe you forgot to add History.fireCurrentHistoryState(); to end of onModuleLoad() method?

You need to set a history token and fire the history change event with current token.
Heres how you could do it:
/ If the application starts with no history token, redirect to a new
// 'homepage' state.
String initToken = History.getToken();
if (initToken.length() == 0) {
History.newItem("homepage");
}
// Add widgets etc
// Add history listener
History.addHistoryListener(yourHistoryHandler);
// Fire the initial history state.
History.fireCurrentHistoryState();

IMHO, home url in form of "proto://hostname#homepage" is ugly :)
1. Just a suggestion:
String token = History.getToken();
String page = token.isEmpty() ? "homepage" : token;
changePage(page);
2. Does Your EntryPoint implement ValueChangeHandler<String>?

Related

iTextSharp difference between implicit explicit NewPage

I use the onStartPage event handler to write a header, works great, but I need to know whether I issued a NewPage() or it was issued due to a page overflow. Is there an elegant way to tell?
Thanks in advance for any help!
You've written a page event implementation, and you've implemented one or more of its methods. You create an instance of this event like this:
MyPageEvent event = new MyPageEvent();
writer.setPageEvent(event);
Whenever the onStartPage() is called, you want to know if it was called from within iText or from your code using the newPage() method. As iText uses the same newPage() method internally, you'll have to use a trick.
Add a memberVariable to your page event application. Something like:
protected boolean myNewPage = false;
Now add this method to your event:
public void newPage(Document document) {
myNewPage = true;
document.newPage();
myNewPage = false;
}
Now whenever you want to trigger a new page, don't use:
document.newPage();
Use this instead:
event.newPage(document);
The onStartPage() method will be called internally for every new page that is initialized, and at that moment, the value of myNewPage will be true whenever the newPage() was triggered by yourself; otherwise it will be false.
I hope this helps; I didn't test it, I'm just telling you what I would try.
(PS: I'm the original developer of iText.)

JavaEE6 Conversation.end doesn't reset conversation.id to 1

Is the conversation.id not reset when conversation.end is called?
Scenario: I have an app that uses conversation scope in CRUD, so when I visit the list page it starts a conversation. Go to the detail and click back will call end conversation and begin conversation again. But while I'm at debug mode I found out that when conversation.end() is called conversation is set to null. Then when I reinvoke conversation.begin() conversation.id is not reset to 1 but rather the last value + 1. Is it correct to behave that way?
What's more puzzling is after logout and login again, the conversation.id pick up the last value + 1.
My environment: Jboss 7.1.3 using javaee-api.
protected void beginConversation() {
if (conversation.isTransient()) {
conversation.begin();
}
}
protected void endConversation() {
if (!conversation.isTransient()) {
conversation.end();
}
}
So basically I have a base entity (where the above code is defined.) extended by all the backing beans. When a list page is render it will call beginConversation. Clicking the back button in detail page will call endConversation.
Why should the conversation id be reset?
The best way to solve those questions is to directly having a look in the specification (in your case CDI 1.0), which states that the container has to generate an id for the conversation, but not how.
Check out this question, which states how it's done in WELD.

How to do code split in a typical GWT mvp project?

My app is a typical GWT application, it has a navigation bar, when click one bar item, the place will be changed and the app will find corresponding activity for that place(done in MasterActivityMapper), then call activity.start(). During the init of activities, the corresponding views were also created. When my app first starts, it will by default select the first navigation bar item.
public class MasterActivitiesMapper implements Activity
{
public Activity getActivity( Place place )
{
if(place equals place1)
{
Activity1 a1= new Activity1();
return a1;
}
else if(place equals place2)
{
Activity1 a2= new Activity2();
return a2;
}
else if(...)
{
....
}
}
}
My app works well except that the initial download size is too large, it will takes 10 seconds to load. I have to use code split the solve this problem.
I read the doc
https://developers.google.com/web-toolkit/doc/latest/DevGuideCodeSplitting
However still can not figure out where/how to split the code, could anybody has experience with this help?
Activity.start, being asynchronous by nature, seems like a good place to put a GWT.runAsync.
There's also the possibility of returning an activity async proxy from your ActivityMapper. See http://code.google.com/p/google-web-toolkit/issues/detail?id=5129 and https://gist.github.com/3038878 for some sample code.

silverstripe dopublish function for ModelAdmin managed Pages

in the silverstripe backend I´m managing certain PageTypes via a ModelAdmin. That works fine so far, the only thing i can´t figure out is how to make a Page being "Published" when saving it.
Thats my code:
class ProjectPage extends Page {
public function onAfterWrite() {
$this->doPublish();
parent::onAfterWrite();
}
}
At the moment I can still see the ModelAdmin-created Pages in the Sitetree and I can see they are in Draft Mode. If I use the code above I get this error:
Maximum execution time of 30 seconds exceeded in
.../framework/model/DataList.php
Many thx,
Florian
the reason why you get "Maximum execution time exceeded" is because $this->doPublish(); calls $this->write(); which then calls $this->onAfterWrite();. And there you have your endless loop.
So doing this in onAfterWrite() or write() doesn't really work
you should just display the save & publish button instead of the save button
But I guess its easier said than done.
Well adding a button is actually just a few lines, but we also need a provide the functions that do what the button says it does.
This sounds like the perfect call for creating a new Module that allows proper handling of Pages in model admin. I have done this in SS2.4, and I have a pretty good idea of how to do it in SS3, but no time this week, poke me on the silverstripe irc channel on the weekend, maybe I have time on the weekend.
I found the same need/lack and I built a workaround that seems to work for me, maybe it can be useful.
public function onAfterWrite()
{
if(!$this->isPublished() || $this->getIsModifiedOnStage())
{
$this->publish('Stage', 'Live');
Controller::curr()->redirectBack();
}
parent::onAfterWrite();
}
Create a class that extends ModelAdmin and define an updateEditForm function to add a publish button to the actions in the GridFieldDetailForm component of the GridField.
public function updateEditForm($form) {
if ( ! singleton($this->owner->modelClass)->hasExtension('Versioned') ) return;
$gridField = $form->Fields()->fieldByName($this->owner->modelClass);
$gridField->getConfig()->getComponentByType('GridFieldDetailForm')->setItemEditFormCallback(function ($form) {
$form->Actions()->push(FormAction::create('doPublish', 'Save & Publish'));
});
}
Then create a class that extends GridFieldDetailForm_ItemRequest to provide an action handler for your publish button.
public function doPublish($data, $form) {
$return = $this->owner->doSave($data, $form);
$this->owner->record->publish('Stage', 'Live');
return $return;
}
Make sure the extensions are applied and you're done.
Or, you could just grab all the code you need from GitHub.

Problem in Large scale application development and MVP tutorial

I recently tried to follow the Large scale application development and MVP tutorial. The tutorial was great but I am having a hard time with a few things.
If you try and add a contact to the list, the contact is created. If you try and add another contact, you are taken to the edit screen of the last contact you created. No more contacts can be added once you add your first contact. What needs to be changed so you can add more than one contact.
Changes I have made to try and get it to work:
Create a new editContactsView each time the add button is pressed. This brings up a blank edit screen, but the new contact still overwrites the previous addition.
Changed contacts.size() to contacts.size()+1 when determining the ID of the new contact.
Actually, there are a couple of problems (from what I can see):
like Lumpy already mentioned, the new Contact created via EditContactPresenter doesn't get an id assigned (it's null). This is because EditContactPresenter uses the default Contact() constructor which doesn't set the id. There are many possible solutions to this: add setting the id in the default constructor (so that you don't have to keep track of the ids somewhere else in the app), delegate that function to your server (for example, make your DB generate the next available id and send it back) or just add a contact.setId(whatever); in the appropriate place in EditContactsPresenter
AppController.java:134 - this example reuses the view (which is a good idea), but it doesn't clear it if you use it for creating a new Contact. Solution: either disable view reusing (just make a new EditContactsView every time) or add a clear() or sth similar to your Views and make the Presenters call it when they want to create a new entry, instead of editing an exisiting one (in which case, the values from the current entry overwrite the old values, so it's ok).
It's weird that this sample was left with such bugs - although I understand that it's main purpose was to show how MVP and GWT go together, but still :/
When a new contact is added it's id is never set. Because the id field is a string it is stored as "". That is how the first contact is added. Now every time you create a new contact you overwrite the contact with key "". To fix this you need to set the value of the id. I did this by changing the doSave method in EditContactsPresenter.
private void doSave() {
contact.setFirstName(display.getFirstName().getValue());
contact.setLastName(display.getLastName().getValue());
contact.setEmailAddress(display.getEmailAddress().getValue());
if(History.getToken.equals("add")
rpcService.updateContact(contact, new AsyncCallback<Contact>() {
public void onSuccess(Contact result) {
eventBus.fireEvent(new ContactUpdatedEvent(result));
}
public void onFailure(Throwable caught) {
Window.alert("Error updating contact");
}
});
else
rpcService.updateContact(contact, new AsyncCallback<Contact>() {
public void onSuccess(Contact result) {
eventBus.fireEvent(new ContactUpdatedEvent(result));
}
public void onFailure(Throwable caught) {
Window.alert("Error updating contact");
}
});
}