Wicket - FileUploadField, Ajax and Preview - wicket

Im using Wicket 1.5 and I need to build a component with a FileUploadField to load an image.
I need an Ajax behaviour to make a preview of image after selected it (without submiting the entire form).
Searching on Google, I found this Event that match when I select the file:
AjaxEventBehavior choose = new AjaxEventBehavior("onChange"){
private static final long serialVersionUID = 1L;
#Override
protected void onEvent(AjaxRequestTarget target) {
Request request = RequestCycle.get().getRequest();
}
};
What I need is the stream of image to put in a little panel that required:
byte[] imgBytes
And obviously I need the same stream to fill a PropertyModel for DB storing.
Thanks

You need to use either AjaxFormSubmitBehavior (will submit the entire form on the given event) or AjaxFormComponentUpdatingBehavior (will submit only the one form component. I'm not sure whether the latter works with file uploads, just give it a try. You can always use the former.
In the model of your FileUploadField you will find a (list of) FileUpload - look at the methods you get, there are input streams and other things available so you can do pretty much anything with the data.

Related

Changing jasper report parameters in runtime

I know, but we really need it.
We have a clear division of labor.
They create templates, I fill them in runtime according to some rules.
Can't teach my business to insert something like this and be sure they really did it ok(so can't move any logic to templates):
$P{risk_types}.get($F{risk_type}) ?: "UNDEFINED"
Also can not fill from files hardcoded in some adapter hadwritten by god-knows-who and unchangeable in runtime. It's a web app. Best option is to find a way to replace that file source from adapter to a ByteArrayStream.
SO:
Need to substitute contents of parameters(also default ones) at runtime.
example:
need to set JSON_INPUT_STREAM
Like this unsolved thread.
https://community.jaspersoft.com/questions/516611/changing-parameter-scriptlet
Really hope not to work on xml level, but xml also can't solve my problem as far as I tried.
Thank you!
The easiest and cleanest way we did this(bypassing usage of tons of deprecated documentation and unfinished bugged undocumented static antipatterned new features):
Create context with repository extension
SimpleJasperReportsContext jasperReportsContext = new SimpleJasperReportsContext();
jasperReportsContext.setExtensions(RepositoryService.class, Collections.singletonList(new MyRepositoryService(jasperReportsContext, yourOptionalParams)));
Fill this way(after compile and other usual actions)
JasperPrint print = JasperFillManager.getInstance(jasperReportsContext).fill(compiled, new HashMap<>());
Now your repository must extend default one to be hack-injected(cause of hodgie coded "isAssignableFrom") successfully
public class PrintFormsRepositoryService extends DefaultRepositoryService {
#Override
public InputStream getInputStream(RepositoryContext context, String uri) {
// return here your own good simple poj inputStream even from memory if you found source
// or pass to another repository service(default one probably)
return null;
}
}

Apache Isis: How to implement your custom submit form or page properly?

I'm new at Apache Isis and I'm stuck.
I want to create my own submit form with editable parameters for search some entities and a grid with search results below.
Firstly, I created #DomainObject(nature=Nature.VIEW_MODEL) with search results collection, parameters for search and #Action for search.
After deeper research, I found out strict implementations for actions (For exapmle ActionParametersFormPanel). Can I use #Action and edit #DomainObject properties(my search parameters for action) without prompts?
Can I implement it by layout.xml?
Then I tried to change a component as described here: 6.2 Replacing page elements, but I was confused which ComponentType and IModel should I use, maybe ComponentType.PARAMETERS and ActionModel or implement my own IModel for my case.
Should I implement my own Wicket page for search and register it by PageClassList interface, as described here: 6.3 Custom pages
As I understood I need to replace page class for one of PageType, but which one should I change?
So, the question is how to implement such issues properly? Which way should I choose?
Thank you!
===================== UPDATE ===================
I've implemented HomePageViewModel in this way:
#DomainObject(
nature = Nature.VIEW_MODEL,
objectType = "homepage.HomePageViewModel"
)
#Setter #Getter
public class HomePageViewModel {
private String id;
private String type;
public TranslatableString title() {
return TranslatableString.tr("My custom search");
}
public List<SimpleObject> getObjects() {
return simpleObjectRepository.listAll();
}
#Action
public HomePageViewModel search(
#ParameterLayout(named = "Id")
String id,
#ParameterLayout(named = "Type")
String type
){
setId(id);
setType(type);
// finding objects by entered parameters is not implemented yet
return this;
}
#javax.inject.Inject
SimpleObjectRepository simpleObjectRepository;
}
And it works in this way:
I want to implement a built-in-ViewModel action with parameters without any dialog windows, smth like this:
1) Is it possible to create smth like ActionParametersFormPanel based on ComponentType.PARAMETERS and ActionModel and use this component as #Action in my ViewModel?
2) Or I should use, as you said, ComponentType.COLLECTION_CONTENTS? As I inderstand my search result grid and my search input panel will be like ONE my stub component?
Thank you.
We have a JIRA ticket in our JIRA to implement a filterable/searchable component, but it hasn't yet made it to the top of the list for implementation.
As an alternative, you could have a view model that provides the parameters you want to filter on as properties, with a table underneath. (I see you asked another question here on SO re properties on view models, so perhaps you are moving in that direction also... I've answered that question).
If you do want to have a stab at implementing that ticket, then the ComponentTYpe to use is COLLECTION_CONTENTS. If you take a look at the isisaddons, eg for excel or gmap3 then it might help get you started.
======= UPDATE TO ANSWER (based on update made to query) ==========
I have some good news for you. v1.15.0-SNAPSHOT, which should be released in the couple of weeks, has support for "inline prompts". You should find these give a user experience very similar to what you are after, with no further work needed on your part.
To try it out, check out the current trunk, and then load the simpleapp (in examples/application/simpleapp). You should see that editing properties and invoking actions uses the new inline prompt style.
HTH
Dan

SlingModels: How to build the form component from foundation (inject PageContext?)

The foundation component from AEM are just plain JSP without much logic in any java bean. I now try to convert the form components java logic into Sling Models. But the start component again is not easy as there are two things to be done (copied from /libs/foundation/components/form/start/start.jsp).
First:
FormsHelper.startForm(slingRequest, new JspSlingHttpServletResponseWrapper(pageContext));
Second:
componentContext.setDecorate(true);
The slingRequest is easy, when I adapt my model from it, but where to I get the pageContext from? I also need it to get the componentContext which can be retrieved through the pageContext.
I tried the following while adapting through SlingHttpServletRequest:
#SlingObject
private PageContext pc;
But this doesn't work.
EDIT:
I figured out how to create the form start component without the pageContext. Though together with the form start, there is the form end and there is one part that uses the pageContext directly (copied from /libs/foundation/components/form/end/end.jsp)
final boolean isSubmittable = FormsHelper.checkRule(resource, slingRequest, pageContext, "submittableRule");
if (isSubmittable || isEditMode) {
Not sure what this boolean is for or rather why it is checked before rendering the buttons.
So either I need a way to inject the pageContext or I need another way to build this form component with Sling Models.
You don't necessarily need to follow same approach, if you look at javadocs, you can use startForm(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException, ServletException

How to make SuggestBox to reliably RPC-call to Server DB in GWTP (Gwt platform) Framework?

I spent many hours to search this info "How to make SuggestBox to reliably RPC-call to Server DB in GWTP (Gwt platform) Framework" but couldn't find any answer about it.
In fact, there were some answers but they were for people who do not use GWTP. For example, i found a website (http://jagadesh4java.blogspot.com.au/2009/03/hi-every-one-this-is-my-first-blog.html) that guide to code SuggestBox & RPC & it suggests these classes:
-Client Side:
+ interface SuggestService extends RemoteService
+ interface SuggestServiceAsync
+ class Suggestions implements IsSerializable, Suggestion
+ class SuggestionOracle extends SuggestOracle
-Server Side:
+ class SuggestServiceImpl extends RemoteServiceServlet implements
SuggestService
I tried to follow up that website but i got error:
[WARN] failed SelectChannelConnector#127.0.0.1:8888
java.net.BindException: Address already in use: bind..........
The above guide clearly was not for people who use GWTP.
My task is I have a dictionary that contains 200k of English words & I want to have a suggest box that when user types any char or word it will look up into DB & suggest accordingly. Ex, when user types "c" it will suggest "cat, car, cut, etc", when typing "car" it will suggest "car service", "carbon", etc.
So I come up with my own solution, even it works but I am feeling I am not doing right thing. My solution is quite simple that I just bring the data from DB down & add them into MultiWordSuggestOracle. Whenever it found a list of word in DB, it won't clear the old data but just keep adding the new list into MultiWordSuggestOracle. However, my program will not constantly call to DB everytime user types a char, but it will call to DB only if the wordInTheMultiWordSuggestOracleList.indexOf(suggestBox.getText(),0)>0. However, there is no way to loop each string in the MultiWordSuggestOracle, so I used List<String> accumulatedSuggestedWordsList=new ArrayList<String>() to store data. Pls see ex:
private final MultiWordSuggestOracle mySuggestions = new MultiWordSuggestOracle();
private List<String> accumulatedSuggestedWordsList=new ArrayList<String>();
private void updateSuggestions(List<String> suggestedWordsList) {
// call some service to load the suggestions
for(int i=0;i<suggestedWordsList.size(); i++){
mySuggestions.add(suggestedWordsList.get(i));
accumulatedSuggestedWordsList.add(suggestedWordsList.get(i));
}
}
#Override
protected void onBind() {
super.onBind();
final SuggestBox suggestBox = new SuggestBox(mySuggestions);
getView().getShowingTriplePanel().add(suggestBox);
suggestBox.addKeyDownHandler(new KeyDownHandler(){
#Override
public void onKeyDown(KeyDownEvent event) {
// TODO Auto-generated method stub
String word=suggestBox.getText();
int index=-1;
for(int i=0; i<accumulatedSuggestedWordsList.size();i++){
String w=accumulatedSuggestedWordsList.get(i);
index=w.indexOf(word,0);
if(index>0)
break;
}
if(index==0 || index==-1){
GetWordFromDictionary action=new tWordFromDictionary(suggestBox.getText());
action.setActionType("getSuggestedWords");
dispatchAsync.execute(action, getWordFromDictionaryCallback);
}
}
});
}
private AsyncCallback<GetWordFromDictionaryResult> getWordFromDictionaryCallback=new AsyncCallback<GetWordFromDictionaryResult>(){
#Override
public void onFailure(Throwable caught) {
// TODO Auto-generated method stub
}
#Override
public void onSuccess(GetWordFromDictionaryResult result) {
// TODO Auto-generated method stub
List<String> suggestedWordsFromDictionaryList=result.getSuggestedWordsFromDictionaryList();
updateSuggestions(suggestedWordsFromDictionaryList);
}
};
The Result: it works but the suggest only show up if i type the "Backspace" button. For ex, when i type the word "car" then no suggested list popup, it only popup "car service, car sale, etc" when i hit the backspace button.
So, can u evaluate my solution? I am feeling i am not doing right. If i am not doing right thing, can u provide a SuggestBox PRC for GWTPframework?
Very Important Note:
How to build a Reliable SuggestBox PRC that prevents the a denial of service attack on our own servers?
What if there are too many calls generated by many people rapidly typing in a suggest box?
Actually I just found an error:
SQL Exception: Data source rejected establishment of connection, message from server: "Too many connections" --> so there must be something wrong with my solution
I knew why i got "Too many connections" error. For example, when i type "ambassador" into the suggest box, & i saw my server call the Db 9 times continuously.
-1st call, it will search any word like 'a%'
-2nd call, it will search any word like 'am%'
-3nd call, it will search any word like 'amb%'
The first problem is that it create too many calls at 1 time, second it is not effective cos the first time call like 'a%' may already contains word that will be called at 2nd time like 'am%', so it duplicate the data. Question is how to code to avoid this ineffectiveness.
Someone suggests to use RPCSuggestOracle.java (https://code.google.com/p/google-web-toolkit-incubator/source/browse/trunk/src/com/google/gwt/widgetideas/client/RPCSuggestOracle.java?spec=svn1310&r=1310)
If you can provide an example of using RPCSuggestOracle.java, that will be great.
I hope your answer will help a lot of other people.
There were an old inspiring blog post, from the Lombardi Development, that I remember addresses almost all questions you are looking for. It took me a while to find that out but, fortunately, it has simply been moved! And the sources are available. Have a look.
Although being old, things in that post still applies. In particular:
use a single connection to avoid explosion of requests, and left free the other ones for other tasks (i.e. avoid to use all the 2-to-8 max parallel browser http connections);
reuse data from a previous requests (i.e., if your request is a substring of the previous one, you may already have the suggestions, hence just filter them client-side).
Other things that come to my mind are:
use a Timer to simulate a little delay in case of fast writers, so you call the server only after a bit (probably an over optimization, but still an idea);
allow to fetch suggestions only on a minimum input length (say, min 3 characters). If you have a lot of possible suggestions, the data returned might be expensive even to parse, specially if - for the search - you decide to adopt a contains instead of startswith strategy;
in case you still have tons of suggestions, you could try to implement a lazy load SuggestionDisplay that simply show you the first, say, 50 suggestions and then, on scroll, all the others in an incremental way using the same input string.
Can't say anything from the GWTP part, I've never used it. But AFAICS seems just like GWT-RPC + dispatch mechanism (command pattern) like the old gwt-dispatch. Should't be hard to use instead of vanilla GWT-RPC.
Also have a look at the other 2 previous articles linked in the one above. Might contain some other useful tips.
Use key Up handler instead of key down handler may be it will solve your problem.
this is because keyDown event is fired before rendering the character.

gwt, many listboxes on the form

I have a form with six listboxes. Data for every listbox loads through rpc.
I want load all data with one request to the server. I think to return Map< String, List < Seriliazible > > with data for all listboxes.
Other ideas ?
Astor's solution is really the best way to do it. I'd enhance it a little so you can have the data for each listbox separated (as I can see you want from your example):
public class ListDataForForms implements Serializable {
private List<String>[] dataList1;
private List<String>[] dataList2;
private List<String>[] dataList3;
getters and setters...
}
Doing it this way allows you to change your mind and send more or less information in the same request anytime you want