Refresh panel in Wicket with BootstrapDownloadLink - java

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.

Related

Android - is there any Function or Way to Search a specific text in an HTML Webview text

Hello to all Android Programmers, is there any way to search a specific word in an HTML Webview? Or lets say when you put a word in search box and search it and then it will automatically scroll to the word or highlight it but the text is not in TextView the text are formatted using WebView? Sure it may be possible when you store a paragraph in the database and it can be searched easily but the problem on it is it isn't formatted like HTML so is this possible?
Please see the image on this link
For Highlighting search word:
titleWebView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
if (searchText != null && !searchText.equals("")) {
int i = titleWebView.findAll(searchText);
Toast.makeText(getApplicationContext(), "Found " + i + " results !",
Toast.LENGTH_SHORT).show();
try {
Method m = WebView.class.getMethod("setFindIsUp", Boolean.TYPE);
m.invoke(titleWebView, true);
} catch (Throwable ignored) {
}
searchText = "";
}
}
});
You can achieve it by reading source of page in webview.
Inside
Add this method in onPageFinished() of webviewclient:
webView.loadUrl("javascript:window.HTMLOUT.processHTML('<html>'+" +
"document.getElementsByTagName('html')[0].innerHTML+'</html>');");
Declaration for above called method processHTML() which helps to
process source html to String/JSON Obj.
#SuppressWarnings("unused")
#JavascriptInterface
public String processHTML(final String html)
{
// Log.i("processed html",html);
Thread OauthFetcher=new Thread(new Runnable() {
#Override
public void run() {
htmlString= Html.fromHtml(html).toString();
// Log.i("htmlString",htmlString);
Gson gson = new Gson();
CustomPojoObject obj = gson.fromJson(htmlString, CustomPojoObject.class);
}
});OauthFetcher.start();
return htmlString;
}

Which is the correct way to load a view/create a page in a GWT Java application

I am now going through my code to ensure it is correct and consistent. Straight way I find that I load a view in two different ways:
One is:
public HikeRecordView() {
//On load of page get the stored view data and create the page
verticalPanel.addAttachHandler(new Handler() {
public void onAttachOrDetach(AttachEvent event) {
if (event.isAttached()) {
rpc = (DBConnectionAsync) GWT.create(DBConnection.class);
ServiceDefTarget target = (ServiceDefTarget) rpc;
String moduleRelativeURL = GWT.getModuleBaseURL() + "MySQLConnection";
target.setServiceEntryPoint(moduleRelativeURL);
horizontalPanel_Existing.clear();
verticalPanel.clear();
AsyncCallback<ViewData> callback = new ViewDataHandler<ViewData>(HikeRecordView.this);
rpc.getViewData(callback);
}
}
});
initWidget(verticalPanel);
}
And the other is:
public PackHolidayView() {
rpc = (DBConnectionAsync) GWT.create(DBConnection.class);
ServiceDefTarget target = (ServiceDefTarget) rpc;
String moduleRelativeURL = GWT.getModuleBaseURL() + "MySQLConnection";
target.setServiceEntryPoint(moduleRelativeURL);
//On load of page render the page
verticalPanel.addAttachHandler(new Handler() {
public void onAttachOrDetach(AttachEvent event) {
verticalPanel.clear();
verticalPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
//On load of page get the Account Level and ID of the account holder.
AsyncCallback<ViewData> callback = new ViewDataHandler<ViewData>(PackHolidayView.this);
rpc.getViewData(callback);
}
});
initWidget(verticalPanel);
}
They both seem to work so which is the best/recommended way to load a view please?
You should think about splitting the code between Model, View and Presenter. Create appropriate layers. Consider using GIN for Dependency Injection.
Read an article located here: http://www.canoo.com/blog/2011/04/05/gwt-dependency-injection-recipes-using-gin/

WebView not showing anything

I have a pretty simple application that lists rows from a database in a tableview. When the user clicks on a row in that list, the application grabs the XML column from that row, and is supposed to display it in a WebView in the same window. Everything other than actually displaying the XML works fine. I've been beating my head on this for a while, but I'm not getting anywhere. Here's the code that the listener calls:
#FXML
private void showXML(QueryRow row) {
String msg = "";
try {
msg = mainApp.getMsg(row.getID().get());
} catch (SQLException e) {
e.printStackTrace();
}
final String fm = msg;
System.out.println(msg);
//tb.setText(msg);
webEngine = webView.getEngine();
// webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
//
// public void changed(ObservableValue ov, State oldState, State newState) {
//
// if (newState == Worker.State.SUCCEEDED) {
// System.out.println("inside");
// webEngine.load(fm);
// //stage.setTitle(webEngine.getLocation());
// }
//
// }
// });
System.out.println("Go baby go!");
webEngine.load(fm);
}
What am I missing?
If you want to load XML and fm is not link then you should probably use
webEngine.loadContent(fm);
/**
* Loads the given HTML content directly. This method is useful when you have an HTML
* String composed in memory, or loaded from some system which cannot be reached via
* a URL (for example, the HTML text may have come from a database). As with
* {#link #load(String)}, this method is asynchronous.
*/
public void loadContent(String content) {
loadContent(content, "text/html");
}
But this will not make xml visible, so if you want your xml to be displayed, you have to put it in some default html page. Something like this:
https://gist.github.com/jewelsea/1463485
or simple way:
webEngine.loadContent(
<textarea readonly style='width:100%; height:100%'>"+ fm +"</textarea>")
Ok, I just tested a little bit. text/html is the correct way, but you need to do some work on your xml data: You have to escape the XML entities (I use commons-lang3 StringEscapeUtils for that) and then wrap all in a preformatted html string:
public class JavaFXTest extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Test to display XML");
BorderPane content = new BorderPane();
WebView webView = new WebView();
WebEngine webEngine = webView.getEngine();
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<tag1>\n <tag2>hello</tag2>\n</tag1>";
String escaped = StringEscapeUtils.escapeHtml4(xml);
String html = "<html><head></head><body><pre>" + escaped + "</pre></body>";
webEngine.loadContent(html, "text/html");
content.setCenter(webView);
primaryStage.setScene(new Scene(content, 400, 300));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
This produces the following window:
Addition: You might need to do some pretty printing on the xml before escaping; I just used hard coded line breaks and spaces.

Editor persist throws "A request is already in progress "

I'm trying to set up a basic editor in gwt. Everything works fine, the editor displays the data and saves but when I try to save again (i.e. press the save button 2 times) it throws me the error "A request is already in progress " in the second save, but the first time the editor saves the data correctly.
//
//Methods that edit and save the editor, located in ComposerEditorContainer class
//
public void edit(RequestContext requestContext) {
editorDriver = GWT.create(Driver.class);
editorDriver.initialize(requestFactory, composerEditor);
editorDriver.edit(composer, requestContext);
}
public void save() {
ComposerRequest composerRequest = (ComposerRequest) editorDriver
.flush();
ComposerProxy newProxy = composerRequest.edit(composer);
composerRequest.persist(newProxy).fire();
}
//
//Events in a presenter that save and initialize the editor
//
eventBus.addHandler(SaveButtonClickedEvent.TYPE,
new SaveButtonClickedEventHandler() {
#Override
public void onSaveButtonClicked(SaveButtonClickedEvent event) {
((ComposerEditorContainer) composerEditorContainer)
.save();
}
});
//This method gets the ComposerProxy from the event and initializes the editor in ComposerEditorContainer (above)
//
eventBus.addHandler(BrowserItemClickedEvent.TYPE,
new BrowserItemClickedEventHandler() {
#Override
public void onBrowserItemClicked(
BrowserItemClickedEvent event) {
requestFactory = GWT.create(AppRequestFactory.class);
requestFactory.initialize(new SimpleEventBus());
ComposerRequest request = requestFactory
.getComposerRequest();
Request<ComposerProxy> req = request.findComposer(event
.getclickedItem().getValue());
req.fire(new Receiver<ComposerProxy>() {
public void onSuccess(ComposerProxy arg0) {
ComposerEditorContainer editorContainer = new
ComposerEditorContainer(
requestFactory, arg0);
editorContainer.edit(requestFactory
.getComposerRequest());
view.clear();
view.addWidget(editorContainer);
composerEditorContainer = editorContainer;
}
});
}
});
//Error that appears when saving for the second time
Caused by: java.lang.IllegalStateException: A request is already in
progress
at
com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext.checkLocked(AbstractRequestContext.java:
960)
at
com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext.editProxy(AbstractRequestContext.java:
510)
at
com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext.edit(AbstractRequestContext.java:
502)
at
com.google.test.client.editor.ComposerEditorContainer.save(ComposerEditorContainer.java:
58)
at com.google.test.client.presenter.BrowserDetailPresenter
$1.onSaveButtonClicked(BrowserDetailPresenter.java:48)
at
com.google.test.client.event.SaveButtonClickedEvent.dispatch(SaveButtonClickedEvent.java:
17)
Answered on the Google Group: https://groups.google.com/d/msg/google-web-toolkit/TfXd_SEJF30/ZTLkfXUQ2vUJ
A RequestContext is a "builder"; you queue things into it and then fire(). Once fire()d, it's no longer usable; you have to create a new one and start over.

Wicket image component not found on page

I get the following problem when trying to display a list of items. For each item, I have to display an image which is dynamically loaded via a Wicket WebResource. The items are loaded step by step — 50 at a time — upon user scrolling, using an Ajax scroll.
[ERROR] 2011-04-19 09:58:18,000 btpool0-1 org.apache.wicket.RequestCycle.logRuntimeException (host=, request=, site=):
org.apache.wicket.WicketRuntimeException: component documentList:scroller:batchElem:666:content:item:3:batchItemContent:linkToPreview:imageThumbnail not found on page com.webapp.document.pages.DocumentListPage[id = 1]
listener interface = [RequestListenerInterface name=IResourceListener, method=public abstract void org.apache.wicket.IResourceListener.onResourceRequested()]
org.apache.wicket.protocol.http.request.InvalidUrlException: org.apache.wicket.WicketRuntimeException: component documentList:scroller:batchElem:666:content:item:3:batchItemContent:linkToPreview:imageThumbnail
not found on page com.webapp.document.pages.DocumentListPage[id = 1] listener interface = [RequestListenerInterface name=IResourceListener, method=public abstract void org.apache.wicket.IResourceListener.onResourceRequested()]
at org.apache.wicket.protocol.http.WebRequestCycleProcessor.resolve(WebRequestCycleProcessor.java:262)
at org.apache.wicket.RequestCycle.step(RequestCycle.java:1310)
at org.apache.wicket.RequestCycle.steps(RequestCycle.java:1428)
at org.apache.wicket.RequestCycle.request(RequestCycle.java:545)
at org.apache.wicket.protocol.http.WicketFilter.doGet(WicketFilter.java:479)
at org.apache.wicket.protocol.http.WicketFilter$$EnhancerByGuice$$51619816.CGLIB$doGet$6()
at org.apache.wicket.protocol.http.WicketFilter$$EnhancerByGuice$$51619816$$FastClassByGuice$$6d42bf5d.invoke()
at com.google.inject.internal.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed(InterceptorStackCallback.java:64)
at com.freiheit.monitoring.PerformanceMonitoringMethodInterceptor.invoke(PerformanceMonitoringMethodInterceptor.java:115)
at com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed(InterceptorStackCallback.java:64)
at com.google.inject.internal.InterceptorStackCallback.intercept(InterceptorStackCallback.java:44)
at org.apache.wicket.protocol.http.WicketFilter$$EnhancerByGuice$$51619816.doGet()
at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:312)
at org.apache.wicket.protocol.http.WicketFilter$$EnhancerByGuice$$51619816.CGLIB$doFilter$4()
How can this problem be solved?
Here is the part of the code responsible for adding the image:
previewLink.add(createThumbnailSmall("imageThumbnail", documentModel));
in
createThumbnailSmall(final String id, final IModel<BaseDocument> documentModel) {
// thumbnailResource is an object that contains the path of the image
if (thumbnailResource != null) {
final WebResource resource = getWebResource(thumbnailResource);
final Image image = new Image(id, resource);
return image;
}
return new InvisibleContainer(id);
}
WebResource getWebResource(final DocumentResource documentResource) {
return new WebResource() {
private static final long serialVersionUID = 1L;
#Override
public IResourceStream getResourceStream() {
return new BaseStreamResource(documentResource);
}
};
}
where BaseStreamResource is the following:
public class BaseStreamResource extends AbstractResourceStream {
private InputStream _fileInputStream = null;
private DocumentResource _resource = null;
public BaseStreamResource(final DocumentResource documentResource) {
_resource = documentResource;
}
#Override
public InputStream getInputStream() throws ResourceStreamNotFoundException {
if (_fileInputStream == null) {
try {
if (_resource == null) {
throw new ResourceStreamNotFoundException("Resource was null");
}
_fileInputStream = _resource.getFileInputStream();
} catch (final ResourceNotAvailableException ex) {
throw new ResourceStreamNotFoundException(ex);
}
}
return _fileInputStream;
}
In HTML:
<a wicket:id="linkToPreview" href="#">
<img wicket:id="imageThumbnail" alt="Attachment"></img></a>
The code added hasn't really added any clues for me, but maybe I can help narrow it down a bit anyway.
The stacktrace includes a reference to com.webapp.document.pages.DocumentListPage, which is likely calling some of the code you've posted. The error indicates a bad url, so debugging into that class, adding debug prints, and looking at the values of any field containing a url might be worthwhile.
It might even help to modify the code in DocumentListPage (maybe temporarily for debugging) to catch org.apache.wicket.protocol.http.request.InvalidUrlException and adding debugging prints specifically when the exception is caught.
This isn't really an answer, but it's too big for a comment, and maybe it'll help you get closer to an answer.
The following solution solved the problem:
- extend WebResource class
- add extended class as a resource to application shared resources
Ex:
public class MyWebResource extends WebResource {
final ValueMap map = new ValueMap();
#Override
public IResourceStream getResourceStream() {
String fileName = getFileName();
File file = new File(basePath, fileName);
if (!file.exists()) {
LOG.error("File does not exist: " + file);
throw new IllegalStateException("File does not exist: " + file);
}
return new FileResourceStream(file);
}
public final void addResource() {
Application.get().getSharedResources().add(getClass().getName(), this);
}
protected String getFileName() {
return getParameters().getString("id");
}
public final String urlFor(final String fileName) {
final ResourceReference resourceReference = new ResourceReference(getClass().getName());
final String encodedValue = WicketURLEncoder.QUERY_INSTANCE.encode(fileName);
map.add("id", encodedValue);
final CharSequence result = RequestCycle.get().urlFor(resourceReference, map);
if (result == null) {
throw new IllegalStateException("The resource was not added! "
+ "In your Application class add the following line:"
+ "MyConcreteResource.INSTANCE.addResource()");
}
String absoluteUrl = RequestUtils.toAbsolutePath(result.toString());
return absoluteUrl;
}
}
In Application class, in init(), I have added MyWebResource to shared resources:
public void init() {
...
new MyWebResource().addResource();
...
}

Categories