I'm not sure if I understand correctly BeanFieldGroup but I hope it should bind values from fields(UI components) to my custom beans (eg POJOs).
Here I have my POJO.
public class JobConfigDTO {
#Max(50)
private String format;
#Max(50)
private String template;
#Max(50)
private String channel;
}
With this code I'm attempting to bind my POJO to checkboxes.
private void test(){
JobConfigDTO jobConfigDTO = new JobConfigDTO();
ComboBox comboChannel = createEditFormCombobox("Channel", "CHANNEL");
ComboBox comboFormat = createEditFormCombobox("Format", "FORMAT");
ComboBox comboTemplate = createEditFormCombobox("Template", "TEMPLATE");
BeanFieldGroup<JobConfigDTO> binder = new BeanFieldGroup<>(JobConfigDTO.class);
binder.setItemDataSource(jobConfigDTO);
binder.setBuffered(false);
binder.bind(comboChannel, "channel");
binder.bind(comboChannel, "channel");
binder.bind(comboFormat, "format");
binder.bind(comboTemplate, "template");
Button btnSave = new Button("Add");
btnSave.addClickListener(new Button.ClickListener() {
#Override
public void buttonClick(Button.ClickEvent event) {
try {
log.debug("jobconfigdto {}", jobConfigDTO);
binder.setBuffered(true);
log.debug("jobconfigdto {}", jobConfigDTO);
binder.commit();
binder.setBuffered(false);
} catch (FieldGroup.CommitException e) {
log.error("Unable to save job config", e);
}
}
});
}
When I set values for comboboxes in form and click add button pojo JobConfigDTO is not filled.
Am I missing something or BeanFieldGroup has another usage? I would like to bind values from checkboxes to my pojo class and validate them at the end.
Related
My problem is simple but I have no clue how to solve it. I have a feedbackPanel and I want to show an error message if the BootstrapDownloadLink fails. With a submit I could easily do:
protected void onSubmit(AjaxRequestTarget target) {
...
error("File_not_found"); //Wicket will print this on the feedback panel
target.add(getModalPanel().getFeedbackPanel()); //But i need to refresh it first
}
But the button is inside a panel which I fill with a populateItem and is the only way I know to insert Bootstrap Styles to it. The code of the button:
BootstrapDownloadLink downloadDocument = new BootstrapDownloadLink(IDITEMREPEATER, file) {
#Override
public void onClick() {
File file = (File)getModelObject();
if(file.exists()) {
IResourceStream resourceStream = new FileResourceStream(new org.apache.wicket.util.file.File(file));
getRequestCycle().scheduleRequestHandlerAfterCurrent(new ResourceStreamRequestHandler(resourceStream, file.getName()));
} else {
error(getString("error_fichero_no_existe"));
/// ???? need to refresh-> getModalPanel().getFeedbackPanel()
}
}
};
downloadDocument.setIconType(GlyphIconType.clouddownload);
downloadDocument.add(new AttributeModifier("title", getString("documentos.descargar")));
downloadDocument.add(new AttributeModifier("class", " btn btn-info negrita btn-xs center-block"));
downloadDocument.setVisible(Boolean.TRUE);
list.add(downloadDocument);
You could create or extend from an AjaxDownloadLink, for example like here.
The main idea is to have an AjaxBehavior that does the download, and you get a public void onClick(AjaxRequestTarget target) in which you can add the FeedbackPanel
downloadBehavior = new AbstractAjaxBehavior()
{
private static final long serialVersionUID = 3472918725573624819L;
#Override
public void onRequest()
{
[...]
ResourceStreamRequestHandler handler = new ResourceStreamRequestHandler(
AjaxDownloadLink.this.getModelObject(), name);
handler.setContentDisposition(ContentDisposition.ATTACHMENT);
getComponent().getRequestCycle().scheduleRequestHandlerAfterCurrent(handler);
}
};
And use that behavior in the onclick:
#Override
public void onClick(AjaxRequestTarget aTarget)
{
String url = downloadBehavior.getCallbackUrl().toString();
if (addAntiCache) {
url = url + (url.contains("?") ? "&" : "?");
url = url + "antiCache=" + System.currentTimeMillis();
}
// the timeout is needed to let Wicket release the channel
aTarget.appendJavaScript("setTimeout(\"window.location.href='" + url + "'\", 100);");
}
You can use target.addChildren(getPage(), IFeedback.class). This will add all instances of IFeedback interface in the page to the AjaxRequestTarget.
You can also use FeedbackPanel.class instead of the interface.
Or use getPage().visit(new IVisitor() {...}) to find a specific feedback panel if you don't want to add others which are not related.
How can I fetch the table to my action class? When onclicking the button this function happens.
This is my action class:
public class Action {
ActionVO avo = new ActionVO();
ActoinForm af = new ActionFrom();
public string loaddata() {
if (af == null) {
PropertyUtils.copyProperties(ActionVO, ActionForm);
HashMap hmInput = new HashMap();
hmInput.put(APPCONSTANT.WORKFLOW_ID, APPCONSTANT.REQ_CODE);
hmInput.put(APPCONSTANT.INPUT_CRETERIA, avo);
rvo.execute(hmInput);
af.setSummaryList((Arraylist) rvo.getResultList());
request.setAttribute("setSummaryList", af.getSummaryList());
request.getSession().setAttribute("", ActionVO.getSummaryList());
return success;
}
}
}
I have a form with the following logic:
TextField name = new TextField<>("name", Model.of(""));
TextField surname = new TextField<>("surname", Model.of(""));
TextField mobile = new TextField<>("mobile", Model.of(""));
TextField phone = new TextField<>("phone", Model.of(""));
HiddenField id = new HiddenField<>("id", Model.of(""));
EmailTextField email = new EmailTextField("email", Model.of(""));
Form form = new Form("formContact") {
#Override
protected void onSubmit() {
super.onSubmit();
Contact contact = new Contact();
contact.setName(name.getValue());
contact.setEmail(email.getValue());
contact.setSurname(surname.getValue());
contact.setMobile(mobile.getValue());
contact.setPhone(phone.getValue());
service.save(contact);
}
};
form.add(id);
form.add(email.setRequired(false));
form.add(name.setRequired(true));
form.add(surname.setRequired(true));
form.add(mobile.setRequired(true));
form.add(phone.setRequired(false));
add(form);
I use that code when a client wants to insert a new Contact, and it works.
What I need now is to handle the update of an existing Contact, so I just need to fill an existing form with values from a known Contact instance:
Contact contact = service.get(1);
How can I do that?
Thanks
I would use CompoundPropertyModel for form so it will update when model is changing and also don't need set data to fields. Send model when you creating page or model, you can send contract instance(even empty one). Let's say your class name is MyPanel, then constructor
MyPanel(String id, IModel<Contract> model) {
super(id, model);
}
Now when you are creating form you can use CompoundPropertyModel benefits(in Contract class should be fields name, surname, mobile,etc with public getters and setters)
#Override
protected void onInitialize() {
super.onInitialize();
Form<Contract> form = new Form("formContact", new CompoundPropertyModel(getModel()){
#Override
protected void onSubmit() {
super.onSubmit();
service.save(getModelObject());
}
});
add(form);
form.add(new TextField<>("name").setRequired(true));
form.add(new TextField<>("surname").setRequired(true));
form.add(new TextField<>("mobile").setRequired(true));
form.add(new TextField<>("phone").setRequired(false));
form.add(new HiddenField<>("id"));
form.add(new EmailTextField("email").setRequired(false));
Let's update contract by button clicking
form.add(new AjaxLink<Void>("updateContract"){
#Override
public void onClick(AjaxRequestTarget target) {
form.setModelObject(service.get(1));
target.add(form);
}
});
You should use the existing contact's data in the models of the form components.
E.g. TextField name = new TextField<>("name", new PropertyModel(contact, "name"));
Also see CompoundPropertyModel.
NewForm.java
public class NewForm extends WebPage {
private Bean bean;
private DropDownClass dropdown;
private String selected = "choice";
void init()
{
bean = new Bean();
dropdown=new DropDownClass("test");
}
public NewForm(final PageParameters page) {
init();
final TextField<String> textname = new TextField<String>("name",Model.of(""));
textname.setRequired(true);
final DropDownChoice<String> dropname = new DropDownChoice<String>("type", new PropertyModel<String>(this, "selected"),
dropdown.getlist());
Form<?> form = new Form<Void>("Form") {
#Override
public void onSubmit() {
final String name = (String) textname.getModelObject();
final String dropdown = (String)dropname.getModelObject();
bean.add(name,dropdown);
final String schema = bean.getJsonSchema().toString();
page.add("schema", schema);
setResponsePage(new NewForm(page));
}
};
Label schemalabel = new Label("schema", page.get("schema"));
add(form);
form.add(textname);
form.add(dropname);
form.add(schemalabel);
}
}
Bean.java
public class Bean
{
private JSONObject jsonSchema;
public JSONObject getJsonSchema() {
return jsonSchema;
}
public void setJsonSchema(JSONObject jsonSchema) {
this.jsonSchema = jsonSchema;
}
public Bean() {
jsonSchema = new JSONObject();
}
public void add(String key,String value)
{
jsonSchema.put(key, value); // I am able to append values each time using "put" or "append" in JSF but not in WICKET.How can I append values in Wicket?
//or jsonSchema.append(key, value); //adding values only once and not appending each time,I enter the values in TextField and DropDown
}
}
In CreateForm.java - I have a Textfield and DropDown. When I enter the values in TextField and DropDown..I am able to convert the values entered in TextField and DropDown as JSON schema from method add(String key,String value) in AttributeInfo.java and display the schema as - {"name":"abc"} //where name is value entered in TextField and abc is from DropDown.
I am able to display the schema only once onSubmit But I need to append the values to schema each time,I enter in TextField and DropDown onSubmit and display in the samepage.
How can I achieve this in Wicket?
I am just a beginner.Any Help would be appreciated.Thankyou in advance.
I dynamic create SourcePollingChannelAdapter. After add new url into db, i create new instance of SourcePollingChannelAdapter andd start it.
Here code:
public SourcePollingChannelAdapter getAdapter(RssStream rssStream) throws MalformedURLException {
String beanIdAdapter = "adapter." + rssStream.getId();
String beanIdSource = "source." + rssStream.getId();
SourcePollingChannelAdapter adapter;
if (context.containsBean(beanIdAdapter)) {
adapter = (SourcePollingChannelAdapter) context.getBean(beanIdAdapter);
}
else {
URL url = new URL(rssStream.getLink());
FeedEntryMessageSource source = new FeedEntryMessageSource(url, "news");
source.setApplicationContext(context);
source.setBeanName("source");
source.setBeanFactory(beanFactory);
source.afterPropertiesSet();
adapter = new SourcePollingChannelAdapter();
adapter.setApplicationContext(context);
adapter.setBeanName(beanIdAdapter);
adapter.setBeanFactory(beanFactory);
adapter.setSource(source);
adapter.setOutputChannel(channel);
adapter.setTrigger(new PeriodicTrigger(5000));
adapter.afterPropertiesSet();
}
return adapter;
}
But, after delete url from db, i need stop and delete SourcePollingChannelAdapter.
public void deleteAdapter(int id) {
final String beanId = "adapter." + id;
if (context.containsBean(beanId)) {
SourcePollingChannelAdapter adapter = (SourcePollingChannelAdapter) context.getBean(beanId);
adapter.stop(new Runnable() {
#Override
public void run() {
BeanDefinitionRegistry beanDefinitionRegistry = (BeanDefinitionRegistry) beanFactory;
beanDefinitionRegistry.removeBeanDefinition(beanId);
}
});
}
}
I create new adaptar, start it and I try to delete. But i got NoSuchBeanDefinitionException. How to solve this problem?
You need to register the bean
if (beanFactory instanceof ConfigurableListableBeanFactory) {
((ConfigurableListableBeanFactory) beanFactory).registerSingleton(
beanIdAdapter, adapter);
}
Although the framework does so, you don't really need to register the source (unless you also need to access it later).
EDIT:
However, the framework is not really designed for this activity - it would be better to keep the references in your own class. See this note.