I'm trying to resolve a deprecation warning The constructor TextInputCell(SafeHtmlRenderer) is deprecated raised in the latest version of GWT (2.6):
Column<InterimReport, String> contextColumn = new Column<InterimReport, String>(
new TextInputCell(new SafeHtmlRenderer<String>() {
#Override
public void render(String result, SafeHtmlBuilder builder) {
builder.appendHtmlConstant(result);
}
#Override
public SafeHtml render(String result) {
return SafeHtmlUtils.fromTrustedString(result);
}
}
)
)
{
#Override
public String getValue(InterimReport ir) {
return ir.get("context");
}
};
The TextInputCell holds a URL (see String result) to some page on the internet. I don't know what to use in its place. I found this HyperlinkCell class but can't work out whether:
this is a good approach (should I be doing something with com.google.gwt.user.client.ui.Anchor instead?)
or
if it's the right approach, how to actually implement it
Given your current SafeHtmlRenderer, which works around a previous bug of TextInputCell's default behavior, you can just switch to the default constructor: new TextInputCell().
Related
I want to implement a dictionary in android using the following method :
private final Dictionary<String,String> allWords = new Dictionary<String, String>() {
However, whenever I try to add it I get this whole mess below it, and when I tried using it , I keep getting an error.
I know I'm supposed to implement the functions in the abstract class but I'm wondering if there is an easier way to do it than to code it manually.
#Override
public int size() {
return 0;
}
#Override
public boolean isEmpty() {
return false;
}
#Override
public Enumeration<String> keys() {
return null;
}
#Override
public Enumeration<String> elements() {
return null;
}
#Override
public String get(Object key) {
return null;
}
#Override
public String put(String key, String value) {
return null;
}
#Override
public String remove(Object key) {
return null;
}
};
I just used
private final HashMap<String,String> allWords = new HashMap<>();
It is because there is already a built-in class called Dictionary in Java. Therefore the IDE ask you to override the member functions. If you want to implement everything from scratch, use another class name. Don't use Dictionary. E.g. name your calss MyDictionary, CustomDictionary, or something like that. Avoid built-in class names.
I'm trying to implement a simple autentication system in Play Framework 2.4.x using Deadbolt 2.
I've followed this guide written by Chaloner and I've implemented my deadbolt handler as you can see here:
public class MyDeadboltHandler extends AbstractDeadboltHandler {
public F.Promise<Optional<Result>> beforeAuthCheck(Http.Context context) {
// returning null means that everything is OK. Return a real result if you want a redirect to a login page or
// somewhere else
return F.Promise.promise(Optional::empty);
}
public F.Promise<Optional<Subject>> getSubject(Http.Context context) {
// in a real application, the user name would probably be in the session following a login process
User user = new User("MyUser", "my.email#info.com");
return F.Promise.promise(() -> Optional.ofNullable(user));
}
public F.Promise<Optional<DynamicResourceHandler>> getDynamicResourceHandler(Http.Context context) {
return F.Promise.promise(() -> Optional.of(new MyDynamicResourceHandler()));
}
#Override
public F.Promise<Result> onAuthFailure(final Http.Context context, final String content) {
// you can return any result from here - forbidden, etc
return F.Promise.promise(() -> Controller.redirect(routes.Application.index()));
}
}
My main controller is this:
public class Application extends Controller {
public Result index() {
return ok(index.render());
}
#SubjectPresent
public Result denyAccess(){
return ok(notAllowed.render());
}
public Result permitAccess(){
return ok(allowed.render());
}
public Result errorPage(){
return ok(errorPage.render());
}
}
The problem appears when I try to access the page rendered by the action denyAccess. In this case I get a NullPointerException on page without a stack trace I can read, as you can see in the following image.
It seems that the method onAuthFailure is never invoked even when I try to access the controller denyAccess.
You can see the complete project here on my github page, it's very short and I think it can help you to understand the problem.
Thank you for your help.
The problem lies in your implementation of HandlerCache:
#Singleton
public class MyHandlerCache implements HandlerCache {
private final Map<String, DeadboltHandler> handlers = new HashMap<>();
public MyHandlerCache() {
handlers.put("DEFAULT_KEY", new MyDeadboltHandler());
}
#Override
public DeadboltHandler apply(final String key) {
return handlers.get(key);
}
#Override
public DeadboltHandler get() {
return handlers.get("DEFAULT_KEY");
}
}
By default, the default handler key name is defined by be.objectify.deadbolt.java.ConfigKeys.DEFAULT_HANDLER_KEY but in MyHandlerCache you use "DEFAULT_KEY". However, when this method is called:
public DeadboltHandler apply(final String key) {
return handlers.get(key);
}
it will receive be.objectify.deadbolt.java.ConfigKeys.DEFAULT_HANDLER_KEY as a key and return null.
I'll make sure this is logged better and made clear in the documentation. To fix your implementation, replace "DEFAULT_KEY" with be.objectify.deadbolt.java.ConfigKeys.DEFAULT_HANDLER_KEY:
#Singleton
public class MyHandlerCache implements HandlerCache {
private final Map<String, DeadboltHandler> handlers = new HashMap<>();
public MyHandlerCache() {
handlers.put(ConfigKeys.DEFAULT_HANDLER_KEY, new MyDeadboltHandler());
}
#Override
public DeadboltHandler apply(final String key) {
return handlers.get(key);
}
#Override
public DeadboltHandler get() {
return handlers.get(ConfigKeys.DEFAULT_HANDLER_KEY);
}
}
I have a page with AjaxLazyLoadPanel, which contain a long-loading list and submitting AjaxButton.
After the AjaxLazyLoadPanel is ready, when I submit, the another long-loading is executing, and after that I need to refresh whole page. This is where I get myself, the code looks as follows:
AjaxButton button1 = new AjaxButton("submit1") {
#Override
protected void onSubmit(AjaxRequestTarget target, Form form) {
someLongWorkingMethod();
setResponsePage(page); //refreshing page
}
};
add(button1);
And it works perfectly. But what I'm trying to do now - is to disable this button or hide this button (or the whole panel if its necessary) when the method is computing, and when the page refresh with setResponsePage I'd like to have this button back.
I've read many posts/mailing lists about it but nothing helped me, I tried all things that I found and placed it before someLongWorkingMethod():
ajaxLazyLoadPanel.setOutputMarkupId(true);
ajaxLazyLoadPanel.setOutputMarkupPlaceholderTag(true);
ajaxLazyLoadPanel.add(new AttributeAppender("style","display:none;"));
ajaxLazyLoadPanel.setVisible(false);
ajaxLazyLoadPanel.setEnabled(false);
target.add(ajaxLazyLoadPanel);
And the same not for ajaxLazyLoadPanel but for "this" (AjaxButton).
Am I doing something terribly wrong or what? Is this what I'm trying to do even possible? I would really appreciate some help.
In your AjaxButton you could override updateAjaxAttributes() and add an IAjaxCallListener which hides the button via jQuery right after you click the button. When the responsePage is rendered the button appears again. The code for the override looks like this:
#Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
attributes.getAjaxCallListeners().add(new IAjaxCallListener() {
#Override
public CharSequence getBeforeHandler(Component cmpnt) {
return "$(\"#" + cmpnt.getMarkupId() + "\").hide()";
}
#Override
public CharSequence getPrecondition(Component cmpnt) {
return "";
}
#Override
public CharSequence getBeforeSendHandler(Component cmpnt) {
return "";
}
#Override
public CharSequence getAfterHandler(Component cmpnt) {
return "";
}
#Override
public CharSequence getSuccessHandler(Component cmpnt) {
return "";
}
#Override
public CharSequence getFailureHandler(Component cmpnt) {
return "";
}
#Override
public CharSequence getCompleteHandler(Component cmpnt) {
return "";
}
});
}
Thanks to #Robert Niestroj answer (but working only in newest Wicket 6), I found solution for Wicket 1.5, I hope it will help someone.
Its just similar idea, but achieved with overriding getAjaxCallDecorator for AjaxButton, and using pure Javascript
AjaxButton button1 = new AjaxButton("submit1") {
String id = this.getMarkupId();
#Override
protected void onSubmit(AjaxRequestTarget target, Form form) {
...
}
#Override
protected org.apache.wicket.ajax.IAjaxCallDecorator getAjaxCallDecorator() {
return new AjaxCallDecorator() {
#Override
public CharSequence decorateScript(Component component, CharSequence script) {
return "document.getElementById(\'"+id+"\').style.display = 'none';"+script;
}
};
}
};
Important thing to remember is to ensure that you are returning script+[your added script], because otherwise your onsubmit action won't happen.
More info (and also onSucces and onFailure versions) in Wicket 1.5 doc
Could you guys please help me find where I made a mistake ?
I switched from SimpleBeanEditorDriver to RequestFactoryEditorDriver and my code no longer saves full graph even though with() method is called. But it correctly loads full graph in the constructor.
Could it be caused by circular reference between OrganizationProxy and PersonProxy ? I don't know what else to think :( It worked with SimpleBeanEditorDriver though.
Below is my client code. Let me know if you want me to add sources of proxies to this question (or you can see them here).
public class NewOrderView extends Composite
{
interface Binder extends UiBinder<Widget, NewOrderView> {}
private static Binder uiBinder = GWT.create(Binder.class);
interface Driver extends RequestFactoryEditorDriver<OrganizationProxy, OrganizationEditor> {}
Driver driver = GWT.create(Driver.class);
#UiField
Button save;
#UiField
OrganizationEditor orgEditor;
AdminRequestFactory requestFactory;
AdminRequestFactory.OrderRequestContext requestContext;
OrganizationProxy organization;
public NewOrderView()
{
initWidget(uiBinder.createAndBindUi(this));
requestFactory = createFactory();
requestContext = requestFactory.contextOrder();
driver.initialize(requestFactory, orgEditor);
String[] paths = driver.getPaths();
createFactory().contextOrder().findOrganizationById(1).with(paths).fire(new Receiver<OrganizationProxy>()
{
#Override
public void onSuccess(OrganizationProxy response)
{
if (response == null)
{
organization = requestContext.create(OrganizationProxy.class);
organization.setContactPerson(requestContext.create(PersonProxy.class));
} else
organization = requestContext.edit(response);
driver.edit(organization, requestContext);
}
#Override
public void onFailure(ServerFailure error)
{
createConfirmationDialogBox(error.getMessage()).center();
}
});
}
private static AdminRequestFactory createFactory()
{
AdminRequestFactory factory = GWT.create(AdminRequestFactory.class);
factory.initialize(new SimpleEventBus());
return factory;
}
#UiHandler("save")
void buttonClick(ClickEvent e)
{
e.stopPropagation();
save.setEnabled(false);
try
{
AdminRequestFactory.OrderRequestContext ctx = (AdminRequestFactory.OrderRequestContext) driver.flush();
if (!driver.hasErrors())
{
// Link to each other
PersonProxy contactPerson = organization.getContactPerson();
contactPerson.setOrganization(organization);
String[] paths = driver.getPaths();
ctx.saveOrganization(organization).with(paths).fire(new Receiver<Void>()
{
#Override
public void onSuccess(Void arg0)
{
createConfirmationDialogBox("Saved!").center();
}
#Override
public void onFailure(ServerFailure error)
{
createConfirmationDialogBox(error.getMessage()).center();
}
});
}
} finally
{
save.setEnabled(true);
}
}
}
with() is only used for retrieval of information, so your with() use with a void return type is useless (but harmless).
Whether a full graph is persisted is entirely up to your server-side code, which is intimately bound to your persistence API (JPA, JDO, etc.)
First, check that the Organization object you receive in your save() method on the server-side is correctly populated. If it's not the case, check your Locators (and/or static findXxx methods) ; otherwise, check your save() method's code.
Judging from the code above, I can't see a reason why it wouldn't work.
It took me some time to realize that the problem was the composite id of Person entity.
Below is the code snippet of PojoLocator that is used by my proxy entities.
public class PojoLocator extends Locator<DatastoreObject, Long>
{
#Override
public DatastoreObject find(Class<? extends DatastoreObject> clazz, Long id)
{
}
#Override
public Long getId(DatastoreObject domainObject)
{
}
}
In order to fetch child entity from DataStore you need to have id of a parent class. In order to achieve that I switched "ID class" for Locator<> to String which represents textual form of Objectify's Key<> class.
Here is how to looks now:
public class PojoLocator extends Locator<DatastoreObject, String>
{
#Override
public DatastoreObject find(Class<? extends DatastoreObject> clazz, String id)
{
Key<DatastoreObject> key = Key.create(id);
return ofy.load(key);
}
#Override
public String getId(DatastoreObject domainObject)
{
if (domainObject.getId() != null)
{
Key<DatastoreObject> key = ofy.fact().getKey(domainObject);
return key.getString();
} else
return null;
}
}
Please note that your implementation may slightly differ because I'm using Objectify4.
I have form with dateTimeField, and ListView.
ListView looks like that:
final ListView<String> countryView = new ListView<String>("country", model.<List<String>>bind("country")) {
#Override
protected void populateItem(final ListItem<String> item) {
final String country = item.getModelObject();
item.add(new ValidationDisplayableLabel("country", country, new String[] { modelPath }));
item.add(new AjaxLink("deleteLink") {
#Override
public void onClick(AjaxRequestTarget target) {
model.getObject().getCountry().remove(country);
if (issPeriod) {
addButton.setVisible(true);
countryTextField.setVisible(true);
findButton.setVisible(true);
}
if (target != null)
target.addComponent(rowPanel);
}
});
}
};
countryTextField = new ValidationDisplayableTextField("countryCodeInput", model.bind("oneCountry"), "job.country.value");
**countryView.setReuseItems(true);**
rowPanel.add(countryView);
rowPanel.add(countryTextField);
addButton.setOutputMarkupPlaceholderTag(true);
rowPanel.add(addButton);
And the addButton looks like that:
AjaxSubmitLink addButton = new AjaxSubmitLink(LinkNames.addCountry.toString()) {
#Override
public void onSubmit(AjaxRequestTarget target, Form form) {
if (model.getObject().getOneCountry() != null)
addCountry();
if (target != null)
target.addComponent(rowPanel);
target.addComponent(form.getPage().get("feedbackPanel"));
}
#Override
protected void onError(AjaxRequestTarget target, Form<?> form)
{
onSubmit(target, form);
}
};
The thing is, that when I fail my dateTimeField (e.g. set hours to 100), enter country code in countryTextField, and press on addButton, it displays validation message in feedback panel, that hour range is incorrect, but don't add the country. This is because my model isn't updated. Maybe there is a way to update it manually? So validation message will be displayed, but the country listView still could be updated?
Submit of the whole form is on other button, so logically it is normal to add a country even if there is a validation error in dateTimeField.
Thanks!
P.S. i've read a lot of posts about similar problem, but most of them were solved with .setReuseItems(true), but it doesn't work in my case.
P.P.S Apache wicket 1.4.17
As an update to this answer, in Wicket 6, you can accomplish this by overriding onError() in the Form:
#Override
protected void onError() {
super.onError();
this.updateFormComponentModels();
}
I faced a similar problem in my project, the workaround I found was to use a special Visitor. It will update the model even though the submitted input is invalid.
public class VisitorUpdateModelWithoutValidation implements FormComponent.IVisitor {
public Object formComponent(IFormVisitorParticipant formComponent) {
if (formComponent instanceof FormComponent) {
final FormComponent<?> formComponent1 = (FormComponent<?>) formComponent;
boolean required = formComponent1.isRequired();
if (required) {
formComponent1.setRequired(false);
}
formComponent1.modelChanging();
formComponent1.validate();
formComponent1.updateModel();
formComponent1.modelChanged();
if (required) {
formComponent1.setRequired(true);
}
}
return Component.IVisitor.CONTINUE_TRAVERSAL;
}
}
Simply use it in the onSubmit method of your behavior : getForm().visitFormComponents(new VisitorUpdateModelWithoutValidation());
You can issue a field.clearInput() on the fields you are updating before you target the update(s).