I'm trying to call a URL which should return me a XML file.
I want to Display this XML file.
Right now I don't know how to make the call to get the return file.
I tryied it with a <p:commandButton process="#this" action="http://..." value="Test" /> but I get 2 warnings.
Warning for file: Couldn't find a Mime-Type, add a Mime-Type mapping in your web.xml
Warning for Ressource: Can not be found or operated.
You need to use for example restfull client to get your xml and parse it.
Here's your content of actionlistener that will be called from your button:
Client client = ClientBuilder.newClient( new ClientConfig().register( LoggingFilter.class ) );
WebTarget webTarget = client.target("http://localhost:8080/JerseyDemos/rest").path("employees");
Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_XML);
Response response = invocationBuilder.get();
Employees employees = response.readEntity(Employees.class);
List<Employee> listOfEmployees = employees.getEmployeeList();
(from http://howtodoinjava.com/jersey/jersey-restful-client-examples/#get-list)
Try this:
action=#{yourBean.yourAction}
Inside your bean:
public void yourAction() {
FacesContext fc = FacesContext.getCurrentInstance();
fc.getExternalContext().redirect("http://...");
fc.responseComplete();
}
I'm not sure if it's needed, but also you might wanna set ajax=false on p:commandButton
Related
I am trying to do form validation in Spring Web Flow. For this I am using a validator class, which is named after the model. Just like it is stated in the documentation.
The validator gets instantiated as a bean but is never called during validation. Any pointers on that issue?
flow config
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-2.4.xsd">
<view-state id="createTotpKeyView" view="/templates/totp/create/create" model="key">
<on-entry>
<evaluate expression="createTotpKeyAction"/>
</on-entry>
<transition on="submit" to="successfullyCreated" bind="true" validate="true"/>
</view-state>
<end-state id="successfullyCreated" view="/templates/totp/create/success"/>
</flow>
This is the action that is called in the view-state.
createTotpKeyAction
#Component
public class CreateTotpKeyAction implements Action
{
String uid = "random";
#Override
public Event execute(RequestContext context) throws Exception
{
try
{
// Create a TOTP key and put it in the view scope
TOTPKey totpKey = client.createTotpKeyForUid(uid, null);
context.getViewScope().put("key", totpKey);
return new Event(this, "success");
}
catch (Exception e)
{
log.error("Error while creating TOTP key for user: " + uid + ".\n" + e.getMessage());
// Put response message in flash scope to show it once
context.getFlashScope().put("fetchingError", true);
return new Event(this, "error");
}
}
}
This is the validator I am trying to use. EDIT renamed to match documentation.
KeyValidator
#Component
public class KeyValidator
{
[...]
public void validateCreateTotpKeyView(TOTPKey key, ValidationContext context)
{
System.out.println("VALIDATE VIEW STATE");
}
public void validate(TOTPKey key, ValidationContext context)
{
System.out.println("DEFAULT VALIDATE");
}
}
I also tried different naming schemes such as TOTPKeyValidator or TotpKeyValidator. None of them worked.
The only thing that is working, is creating a validation method in the TOTPKey class, but I don't want to use that approach.
In addition this is the log file produced during the attempted validation
Log
Mapping request with URI '/totp/create' to flow with id 'totp/create'
Resuming flow execution with key 'e5s1
Locking conversation 5
Getting flow execution with key 'e5s1'
Getting FlowDefinition with id 'totp/create'
Resuming in org.springframework.webflow.mvc.servlet.MvcExternalContext#2b551393
Restoring [FlowVariable#3b66a2de name = 'key', valueFactory = [BeanFactoryVariableValueFactory#2fbc89 type = TOTPKey]]
Processing user event 'submit'
Resolved model twofa.core.domain.TOTPKey#505439d0
Binding to model
Adding default mapping for parameter 'execution'
Adding default mapping for parameter 'totpKeyId'
Adding default mapping for parameter 'token'
Adding empty value mapping for parameter 'eventId_submit'
Validating model
Event 'submit' returned from view [ServletMvcView#19f8532f view = org.springframework.web.servlet.view.velocity.VelocityLayoutView: name '/templates/totp/create/create'; URL [/templates/totp/create/create.vm]]
Executing [Transition#2feb5361 on = submit, to = successfullyCreated]
Exiting state 'createTotpKeyView'
Entering state 'successfullyCreated' of flow 'totp/create'
Executing org.springframework.webflow.action.ViewFactoryActionAdapter#423fa131
Rendering MVC [org.springframework.web.servlet.view.velocity.VelocityLayoutView: name '/templates/totp/create/success'; URL [/templates/totp/create/success.vm]] with model map [{currentUser=null, flashScope=map[[empty]], flowRequestContext=[RequestControlContextImpl#70144045 externalContext = org.springframework.webflow.mvc.servlet.MvcExternalContext#2b551393, currentEvent = submit, requestScope = map[[empty]], attributes = map[[empty]], messageContext = [DefaultMessageContext#149807b4 sourceMessages = map[[null] -> list[[empty]]]], flowExecution = [FlowExecutionImpl#1c4b2c3e flow = 'totp/create', flowSessions = list[[FlowSessionImpl#6eea5d26 flow = 'totp/create', state = 'successfullyCreated', scope = map['key' -> twofa.core.domain.TOTPKey#73f32d0a]]]]], flowExecutionKey=e5s1, flowExecutionUrl=/totp/create?execution=e5s1, key=twofa.core.domain.TOTPKey#73f32d0a}]
Finished executing org.springframework.webflow.action.ViewFactoryActionAdapter#423fa131; result = success
Completed transition execution. As a result, the flow execution has ended
Removing flow execution '[Ended execution of 'totp/create']' from repository
Ending conversation 5
Unlocking conversation 5
It says Validating Model but nothing happens...
It came down to a wrong import statement in my validator class.
Using org.relaxng.datatype.ValidationContext instead of org.springframework.binding.validation.ValidationContext will not work.
As soon as I add the librarys icefaces.jar icepush.jar icefaces_ace.jar to my classpath in order to use ACE components, my SaveAs dialog won't popup? I'm not sure if this is a bug but without the librarys in classpath it works. Here's my save as method :
public void downloadFile(String propertyPath) throws IOException {
ProxyFile fileToDownload = repBean.downloadFile(propertyPath);
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
response.reset(); response.setContentType(fileToDownload.getContentType());
response.setHeader("Content-Length", String.valueOf(fileToDownload.getLength()));
response.setHeader("Content-disposition", "attachment; filename=\"" + fileToDownload.getName() + "\"");
BufferedInputStream input = null;
BufferedOutputStream output = null;
try {
input = new BufferedInputStream(fileToDownload.getContent());
output = new BufferedOutputStream(response.getOutputStream());
byte[] buffer = new byte[10240];
for (int length; (length = input.read(buffer)) > 0;) {
output.write(buffer, 0, length);
}
} finally {
output.close();
input.close();
facesContext.responseComplete();
}
}
You can't download files using ajax.
Ajax is under the covers executed by JavaScript's XMLHttpRequest object. The request will be successfully executed and the response will be successfully retrieved. However, JavaScript has no facility to write the response to client's disk file system, nor to force a Save As dialogue with the given response. That would be a huge security breach.
The cause of your concrete problem is ICEfaces itself. Namely, when you integrate ICEfaces in a JSF web application, all standard <h:commandXxx> links/buttons will silently be turned into ajax-enabled ones which indeed causes confusion among starters. Make sure that the download link/button isn't implicitly using ICEfaces-introduced ajax facility. As per their wiki page on the subject, you need to explicitly nest a <f:ajax disabled="true"> to disable this.
Disable Ajax for a Component
You can also disable Ajax at the level of the individual component:
<h:commandButton value="Send" actionListener="#{bean.sendMessage}">
<f:ajax disabled="true"/>
</h:commandButton>
Apply it on your download link/button.
I generate an exportList in my Bean:
public void exportExcel() throws WriteException {
try {
FacesContext context = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment; filename=\"hours.xls\";");
OutputStream out = response.getOutputStream();
WorkbookSettings ws = new WorkbookSettings();
ws.setLocale(new Locale("de", "DE"));
WritableWorkbook workbook = Workbook.createWorkbook(out, ws);
WritableSheet sheet = workbook.createSheet("Sheet1", 0);
sheet.addCell(new Label(0, 0, "ID", bold));
int row = 1;
for (Hour hour : this.listHours) {
sheet.addCell(new Label(0, row, String.valueOf(hour.getId())));
row++;
}
SheetFormatter.setOptimalColumnWidth(sheet);
workbook.write();
workbook.close();
response.flushBuffer();
context.responseComplete();
context.addMessage(null, new FacesMessage("Liste Exportiert"));
}
catch (Exception e) {
}
}
In my page I call method in p:commandButton
<p:commandButton value="#{msg.export}" update="growl"
immediate="true" action="#{hoursView.exportExcel()}" />
My page will not open the excel-List... If if add the attribute ajax="false" it works but then update will not execute...
For information my Bean is SessionScoped if this makes some differences
Your first mistake is that you're trying to download a file using ajax. That just isn't possible. Ajax is executed by JavaScript code which has due to security reasons no facilities to force a "Save as" dialogue and/or write the retrieved response to the local disk file system. That would otherwise open doors to various nasty security breach possibilities.
So, using ajax="false" is absolutely necessary.
Your second mistake is that you're trying to mix different responses into a single response. That just isn't possible. You can only return either a file download, or an ajax update, not both. To retrieve two different responses, you basically need to let the client send two different requests. You could approach this as follows:
Let client send an ajax request to backing bean.
Let server create and save Excel file in server's temporary storage system and generate an unique URL so that it could be accessed by a servlet.
Let server send an ajax response containing the message and the URL.
Let client display the message and invoke a new GET request on the URL. You could use window.location=url; to let JavaScript invoke a new GET request on the URL.
Hi all I have a problem when working with struts validation as the following :
an edit profile page loaded , when user click save a validation should be executed if an error exist a redirect to the same page must happen with validation error showed, and data loaded, else execute method called. what happen that a errors list has values but no errors showed up in the screen, a snap of my code is :
I am using struts 1
<action path="/selectUserAction" validate="true" input="/selectUserAction.do" type="com.bg.sharjah.usermanagement.manageusersgroups.web.actions.SelectUserAction"
name="editUserProfileFormBean" scope="request">
#Override
public ActionErrors validate(ActionMapping mapping,
HttpServletRequest request) {
//Logger.getAnonymousLogger().log(Level.WARNING,"");
ActionErrors errors = new ActionErrors();
try{
errors = super.validate(mapping, request);
System.out.println("validate <<<<<<<<<<< "+errors.size());
}catch(Exception e)
{
e.printStackTrace();
}
return errors;
// Validation.match(errors, password, confirmPassword);
//Validation.match(errors, email, confirmEmail);
}
Note:
my form bean is used with different actions, also I need to know how to redirect to the same page using input attribute ?
Thanx all I find out the problem it's a resource bundle issue.
I have a project using Struts2 on the server side and I am trying to make it work with jqGrid (using JSON format). I have several tables made with jqGrid and I am using the add/edit/delete buttons from navGrid.
The main problem I have is with server validation error messages. I have created custom validators and they work with jsp pages, using s:fielderror, but I don't know how to make them work for add/edit popups from jqGrid. I am aware that jqGrid provides the users with custom validation on client, but this has its limitations(think about testing whether the email of a user is unique, you definitely must use the database for that, or if some fields depend on each other and must be tested together, like if isManager is true, then the managerCode must be not empty and vice versa...).
When I use the client validation, there is a message in the add/edit window whenever an error occurs. Can I somehow display my server validation error messages in the window in the same way?
I managed to solve the issue. I will explain how using a simple custom validator for age field, which must be > 18 for an Employee. It is supposed next that the validator was already declared in validators.xml and mapped on the action and that the message in case of ValidationException is "An employee should be older than 18.".
Using Firebug, I figured out that the id of the error area in the form is FormError. It is possible to configure a callback function errorTextFormat in jqgrid, in order to get a response from the server and process it. In the jqgrid configuration, one could write
errorTextFormat : errorFormat,
with
var errorFormat = function(response) {
var text = response.responseText;
$('#FormError').text(text); //sets the text in the error area to the validation //message from the server
return text;
};
The problem is now that the server will send implicitly a response containing the whole exception stack trace. To deal with it, I decided to create a new result type.
public class MyResult implements Result {
/**
*
*/
private static final long serialVersionUID = -6814596446076941639L;
private int errorCode = 500;
public void execute(ActionInvocation invocation) throws Exception {
ActionContext actionContext = invocation.getInvocationContext();
HttpServletResponse response = (HttpServletResponse) actionContext
.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse");
Exception exception = (Exception) actionContext
.getValueStack().findValue("exception");
response.setStatus(getErrorCode());
try {
PrintWriter out = response.getWriter();
out.print(exception.getMessage());
} catch (IOException e) {
throw e;
}
}
/**
* #return the errorCode
*/
public int getErrorCode() {
return errorCode;
}
/**
* #param errorCode the errorCode to set
*/
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
}
It must also be configured in struts.xml as follows:
<package name="default" abstract="true" extends="struts-default">
...
<result-types>
<result-type name="validationError"
class="exercises.ex5.result.MyResult">
</result-type>
</result-types>
...
<action name="myaction">
...
<result name="validationException" type="validationError"></result>
<exception-mapping result="validationException"
exception="java.lang.Exception"></exception-mapping>
</action>
...
</package>
These are the steps I followed to get a validation error message in the add/edit window and now it works.