I am using Primefaces/JSF in combination with pure javascript tools in order to implement an image viewer & annotator. Image viewer is built upon the OpenLayers framework.
When the user annotates (draws shapes) on the canvas, a JSON object is created and upon Save action passed to the back bean. Back bean retrieves the object (deserialized) and stores it in to a file.
Here is the relevant code:
OpenLayers javascript (image-viewer.js):
function initialiseMap(){'
...
map = new OpenLayers.Map(imageEditorID, options);
imageLayer = new OpenLayers.Layer.TMS(imgURL, "", {
...
});
map.addLayer(imageLayer);
var vlayer = new OpenLayers.Layer.Vector("Editable");
map.addLayer(vlayer);
//draw controls and shape tools
...
//then define save action
var save = new OpenLayers.Control.Button({
...
var GEOJSON_PARSER = new OpenLayers.Format.GeoJSON();
var vectorLayerAsJson = GEOJSON_PARSER.write(vlayer.features);
//and finally post to server layer with drawn shapes
sendJSONToServer([{name:'param', value:vectorLayerAsJson}]);
...
The above Image Viewer/Map tool, is loaded via an p:outputPanel component of primefaces and uses sendJSONToServer remoteCommand to get JSON layer:
<h:head>
<script src="#{facesContext.externalContext.requestContextPath}/js/image-viewer.js" />
...
<h:body>
<h:form id="imageEditor">
<p:fieldset legend="Viewer">
...
// inoutHidden does not have on* events? how am i going to post to image-viewer.js?
<h:inputHidden value="#{imageAnnotations.fetchJsonString()}" />
...
<p:outputPanel layout="block" styleClass="imageEditorImagePanel" />
<p:remoteCommand immediate="true" name="sendJSONToServer" action="#{imageAnnotations.actionOnString}" />
</p:fieldset>
....
Finally in the backbean the JSON object is fetched and stored in a file (implementation is raw):
#ManagedBean(name="imageAnnotations")
public class ImageAnnotations {
//actionOnString fetches and saves the JSON string - this is a raw impementation
public String actionOnString() {
//Do the job and get and save JSON string
}
public String fetchJsonString(){
//Do the job and get JSON string
return jsonString;
}
}
The question is How am i going to use a JSF or primefaces element to make available the imageAnnotations.fetchJsonString() value for fetching from within js?
Even I can't give all answers, for me the filling of your hiddenInput should be managed as following:
#ManagedBean(name="imageAnnotations")
public class ImageAnnotations {
private String jsonString;
public void anyMethodFillingOrInitializingTheJSONString() {
this.jsonString = resultOfYourWork();
}
public String getJsonString(){
return this.jsonString();
}
public void setJsonString(String item) {
this.jsonString = item;
}
}
When you reload this hidden input field, just be sure to trigger a javascript parsing the String and updating your client-side Model. This can be done via the on* - events you can connect with Primefaces buttons.
Guys, can anybody help with the other parts?
Related
Problem: Checkboxes values are not being bound to my form, properly. The result is that all my boolean values are null (at least the ones not being bound), and the existing ones are not being updated with values changed by the user.
Details: I'm aware that checkboxes are not submitted to the server if they are not selected. However, I do see the values in the request when hooking up an Eclipse debugger. The data is populated using jQuery/Datatable, but the data is posted back to the server using a form submit.
Spring MVC Version: 3.2.8
I'm assuming its configuration, but I'm not seeing where I am wrong. Here is a small code snippet of what I'm doing in my controller.
#Controller
public class CheckboxController {
...
#RequestMapping(value = "saveCheckboxes*", method = RequestMethod.POST)
public String saveCheckboxes(#ModelAttribute(SESSION_FORM_KEY) CheckboxForm form, BindingResult result, ModelMap model) {
// VALIDATE HERE...
if ( !result.hasErrors() ) {
// SAVE
}
else {
// DON'T SAVE (alert user)
}
}
}
So Spring MVC is used to binding request inputs to my form. The form is defined below, which has a list of summary objects with a boolean property.
public class CheckboxForm {
private List<Summary> summaries;
...
}
public class Summary {
private boolean selected;
...
}
I use jQuery/Datatables to populate my online grid of data. The inputs are created dynamically using a callback within datatables.
var tableWidget = (function($) {
init = function() {
...
"aoColumnDefs": [
{ "aTargets": [0], "sName": "", "mData": "selected" "stype": "html", "sClass": "center", "mRender": renderCheckbox, "bSortable":false, "sWidth": "50px" }
...
};
renderCheckbox = function(source, type, row) {
var $name = 'checkboxForm.summaries['+row.index+'].selected';
return createCheckbox($name, source);
};
createCheckbox = function(name, checked) {
var $checked = (checked === true) ? ' checked="checked"' : '';
return '<input type="checkbox" name="'+name+'" value="true"'+$checked+'/><input type="hidden" name="_'+name+'" value="on"/>';
}
...
))(jQuery);
After all of this, I hooked up the debugger and traced it into the WebDataBinder. I found that it seems to throw and exception in the method:
public boolean isWritableProperty(String propertyName)
saying the property cannot be evaluated. This happens for each property returned. However, I can confirm that what is in the request is the very inputs that I am expecting.
First, unless you know why avoid relative URL in #RequestMapping methods. It is a common cause of errors.
Next, as you directly generate your checkboxes without all the bells and whistles that adds spring:checkbox, you wont't get automatic error messages, and could experience problems in getting last checkboxes values if they are unchecked, as they will not be transmitted by browser and Spring will never see them giving a shorter list (or even an empty list if all are unchecked).
That being said, your problem is that you use checkboxForm.summaries[index].selected where Spring would expect only summaries[index].selected. Remove checkboxFormand your controller should affect values to the #ModelAttribute CheckboxForm form.
I am attempting to load a custom component(descending from UIInput). I then encode an html input back to the client. My component loader is thus:
#FacesComponent("TomsWidgetComponent")
#SessionScoped
public class TomsWidgetComponent {
public TomsInput getNewInput(UIComponent parent)
{
ExpressionFactory factory = getFacesContext().getApplication().getExpressionFactory();
TomsInput newComponent = (TomsInput) getFacesContext().getApplication().createComponent(getFacesContext(), "org.tom.example.toms.TomsInput", "org.tom.example.toms.TomsInput");
String newId = FacesContext.getCurrentInstance().getViewRoot().createUniqueId();
newComponent.setId(newId);
elements.put(newId, newComponent);
newComponent.setInputData(new InputData());
ValueExpression valueExpression = factory.createValueExpression(getFacesContext().getELContext(),"#{tomsInput.string}",String.class);
newComponent.setValueExpression("value", valueExpression);
getChildren().add(newComponent);
pushComponentToEL(getFacesContext(), newComponent);
return newComponent;
}
html:
<"input type="tel" id="j_id2" oninput="mojarra.ab(this,event,0,'execute',0)" /input >"
The input shows up just fine, but ajax event never seems show up in my component. I've tried several permutations, with the key on setValueExpression, and adding behavior listeners.
...
Ive gotten passed the exceptions but the Ajax now coming back from the form is causing my component to reload. It's content is:
tomswidgetform=tomswidgetform&j_id2=fffdsdfgbg&javax.faces.ViewState=-6270730402975544133%3A7227399941332846704&javax.faces.source=j_id2&javax.faces.partial.event=input&javax.faces.partial.execute=j_id2%20j_id2&javax.faces.behavior.event=change&AJAX%3AEVENTS_COUNT=1&javax.faces.partial.ajax=true
Any idea what might be wrong? Thanks.
I want to observe the upload percentage of a file upload from GWT.
In JavaScript you can use a XMLHttpRequest and add an event listener like this:
var oReq = new XMLHttpRequest();
oReq.upload.addEventListener("progress", updateProgress, false);
// progress on transfers from the server to the client (downloads)
function updateProgress (oEvent) {
if (oEvent.lengthComputable) {
var percentComplete = oEvent.loaded / oEvent.total;
// ...
} else {
// Unable to compute progress information since the total size is unknown
}
}
(The above code is from here.)
This is also done very easily in jQuery as:
var $request = $.ajax({
xhr: function() {
xhrNativeObject = new window.XMLHttpRequest();
//Upload progress
xhrNativeObject.upload.addEventListener("progress", function(event) { ... }
}
});
I want to do the same with GWT. I could use a RequestBuilder to send a request, but this is only a high level wrapper around the XMLHttpRequest JavaScriot object. Another possibility would be to use the GWT XMLHttpRequest class which is a JSNI wrapper of the JavaScript XMLHttpRequest.
My problem:
How can I add a progress listener to the XMLHttpRequest or the RequestBuilder?
I used before gwt-upload library.
You dont need to rediscover America.
Thanks for moxie group
gwt-upload-project page
//upload spring service conroller
#RequestBody public void uploadImage(#RequestParam("file") MultipartFile file ){
//what ever you want
}
XML Configuration
<bean id=multipartResolver" class ="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
GWT Elemental contains all you need already AFAICT.
I am working with a web application in which there is a Java Applet that captures an image from a wacom device into a RenderedImage object. The applet itself is embedded into a JSF 2.0 page.
I need to pass the created RenderedImage from Applet to a JSF backing bean so that it would be a part of a User object. My backing bean is view scoped.
I'm really lost with this. I've been searching for a good example on how this goal can be achieved. Should I use JSObject, or should I send an image to a servlet?
Can you offer some advice on how to solve this problem?
You problem can be divided into the following sub-steps:
Create a byte array from your BufferedImage that is holding its data;
Encode the data properly so that it won't be damaged/modified while it is being sent to the server as a string, for example by using Apache Commons Base64 codec;
Save the data as a hidden form field via Applet-to-JavaScript communication;
Send POST request to the server by, for example, triggering <h:commandButton>'s onclick;
Write encoded string to a java bean property in a standard JSF way;
Decode the string to get the byte array representing the image;
Recreate the image from the byte array and inject it in your view scoped bean.
That said, let's move on to implementing that agenda.
In your applet you'll have a method that will do points (1) - (4). Call it in a usual way, after you obtain the image:
Java Applet method:
public void processImage() throws IOException, JSException {
BufferedImage image = createBufferedImage();//the way you get the image
/* point 1 */
ByteArrayOutputStream bs = new ByteArrayOutputStream();
ImageIO.write(image, "png", bs);
bs.flush();
byte[] imageByteArray = bs.toByteArray();
bs.close();
/* point 1 */
String imageAsString = Base64.encodeBase64String(imageByteArray);//point 2
/* points 3-4 */
JSObject window = JSObject.getWindow(this);
window.call("writeImageValue", new Object[] {imageAsString});
/* points 3-4 */
}
JSF page (form and JavaScript):
<script>
function writeImageValue(imageValue) {
document.getElementById('image').value = imageValue;//point 3
document.getElementById('image-form:submit').click();//point 4
}
</script>
<h:form id="image-form">
<input type="hidden" id="image" name="image" />
<h:commandButton id="submit" action="#{imageSubmitBean.submitImage}" style="display:none" />
</h:form>
JSF managed bean:
#ManagedBean
#RequestScoped
public class ImageSubmitBean {
#ManagedProperty("#{param.image}")//point 5
private String imageAsString;//getter+setter
#ManagedProperty("#{userBean}")//your view scoped bean
private UserBean userBean;//getter+setter
public String submitImage() throws IOException {
byte[] imageByteArray = Base64.decodeBase64(imageAsString);//point 6
/* point 7 */
InputStream is = new ByteArrayInputStream(imageByteArray);
BufferedImage image = ImageIO.read(is);
is.close();
userBean.setUserImage(image);//update your view scoped bean
/* point 7 */
return null;
}
}
I am binding a multi select list in spring the item does not get its data from the DAO the data is added from another select option list. The user clicks a button and the data is sent to the multi select option list using jquery.
When the form is posted databinding does not happen for the item since its a complex data type so i registered a CustomEditor and attached it to the #initbinder.
EDITED
I have updated the code the CollectionEditor is now returning a list of citizens back to the view however i am unable to get the data in the list to fill the select option. I am trying to add elements to the list however the jsp still selects remain null when return form the server.
Under is the code:
CustomCollectionEditor
#InitBinder("crime")
protected void initBinder(WebDataBinder binder, HttpServletRequest request, ServletRequestDataBinder victimbinder){
victimbinder.registerCustomEditor(List.class, "victims", new CustomCollectionEditor(List.class){
protected Object convertElement(Object element){
Citizens victims = new Citizens();
String ssNumber = "";
if (element instanceof String){
ssNumber = (String) element;
}
logger.debug("element is ;" +element);
try {
int socialSecurityNumber = Integer.parseInt(ssNumber);
victims = citizenManager.getCitizen(socialSecurityNumber);
} catch (NumberFormatException e) {
logger.error(e.getMessage());
} catch (Exception e) {
logger.error(e.getMessage());
}
return victims;
}
});
Jsp that is filled from DAO in controller
This contains data filled form DAO class when the button is clicked it takes the data from the list on appends it to the other list under which is bind to the POJO
<label>Victims List</label><buttonid="addVictimBtn">/button>
<form:select path="" id="dbvictims" title="Victims Of Crime" class="victimLst">
<form:options items="${dbvictims.dbvictimList}" itemValue="socialSecurityNumber" itemLabel="name"/>
</form:select>
Jsp select item that is bind to POJO
<label>Victims In Crime</label><button id="removeVictimBtn">-</button>
<form:select path="victims" id="victims" title="Victims Of Crime" multiple="multiple" class="victimLst">
<form:options items="${victimList}" itemValue="socialSecurityNumber" itemLabel="name"/>
</form:select><form:errors path="victims" class="errors" />
The Solution to this issue was very simple all of the work was already done in the CustomCollectionEditor. This is important when binding complex data types such as above. There may be other approaches to doing this however i find this to be a very clean and simple approach.
The return statement is very important since it binds to the item attribute of the element in the view. CustomCollectionEditor return a list of objects (victims) The use of the DAO gets the object from the database. This is important since the post only sends the select value not the label, hence we reconstruct the list and resend to the view.
The part of this that i omitted was passing the List Object from the controller back to the view.
Controller
#RequestMapping(value="save.htm", method = RequestMethod.POST)
public ModelAndView handleSave(#Valid #ModelAttribute Crime crime,
BindingResult result,
ModelMap m,
Model model) throws Exception {
if(result.hasErrors()){
model.addAttribute("victimList",crime.getVictims());
return new ModelAndView("*Your View*");
...............