简体   繁体   English

异常后保持对话(在Pages.xml中处理)

[英]Maintain Conversation After Exception (Handled in Pages.xml)

I'm working in a project that I didn't originally start, so there are a lot of artifacts and conventions that I cannot change without considerable effort. 我正在一个我最初没有开始的项目中工作,所以有很多工件和约定我需要付出大量努力才能更改。 Anyway, here's the problem. 无论如何,这就是问题所在。 I need to do multiple file uploads (that are "children" to the entity that is being edited on the "main" parent page) that get cached on the server so that they can be sent somewhere else if/when the user submits. 我需要将多个文件上传(在“主”父页面上正在编辑的实体的“孩子”)上传到服务器上,以便在用户提交时将其发送到其他地方。 The files uploaded also include metadata that the user enters. 上载的文件还包括用户输入的元数据。 The best way I have figured to do this is to render a "dialog" that has an iframe that does the uploading and has the input for the metadata. 我想做到这一点的最好方法是渲染一个“对话”,该对话具有一个iframe进行上传并具有元数据的输入。 Then I created an override (using install precedence) of Seam's multipart filter that uses the Apache file upload jar and a custom request wrapper that carries my information into the action call on the server. 然后,我创建了Seam的多部分过滤器的覆盖(使用安装优先级),该过滤器使用Apache文件上传jar和自定义请求包装器,该包装器将我的信息携带到服务器上的操作调用中。 All goes well unless I throw an exception out of the filter, for example, if the request size is too big. 除非我将异常从过滤器中抛出,否则一切都会顺利进行,例如,如果请求大小太大。 The exception is caught and handled by a pages.xml declaration. 异常是由pages.xml声明捕获并处理的。

<exception class="org.jboss.seam.web.FileUploadException">
     <redirect view-id="#{facesContext.externalContext.requestServletPath}">
          <message severity='ERROR'>#{org.jboss.seam.handledException.message}</message> 
     </redirect>
</exception>

When I normally submit the form in my dialog frame, the conversation in the frame remains (as I want), when the exception is caught, I get a new one (as I don't want). 当我通常在对话框框架中提交表单时,框架中的对话(根据我的意愿)仍然存在,当捕获到异常时,我得到了一个新对话(如我所愿)。 I want the error messages passed by the exception shown in the global messages area of the frame, but I need to remain in the same conversation as before since the "children" that are being added in the dialog are children to the "parent" entity in the main page. 我希望通过框架的全局消息区域中显示的异常传递的错误消息,但是我需要保持与以前相同的对话,因为在对话框中添加的“孩子”是“父”实体的孩子在主页上。 Here is the form inside the frame code. 这是框架代码中的表格。 I have tried s:button (does not submit the form), tried parameters, and tried hidden inputs with the conversation id. 我尝试了s:button(不提交表单),尝试过的参数以及尝试了带有对话ID的隐藏输入。

<h:form id="attachmentModalForm" enctype="multipart/form-data" autocomplete="off" style="background-color: #FFFFFF;">
     <ui:include src="layout/messages.xhtml" />
     <div id="attachmentModalMain" class="modalMain">
          <s:decorate id="attachmentDescriptionDecoration" template="layout/edit.xhtml" styleClass="twoCol">
               <ui:define name="label">#{messages['contents.attachmentDialog.label.description']}<s:span styleClass="required">*</s:span></ui:define>
               <h:inputText id="attachmentDescription" value="#{attachmentAction.description}" styleClass="textbox" />
          </s:decorate>
          <s:decorate id="attachmentFileDecoration" template="layout/edit.xhtml" styleClass="twoCol">
               <ui:define name="label">#{messages['contents.attachmentDialog.label.file']}<s:span styleClass="required">*</s:span></ui:define>
               <input id="attachmentFile" name="attachmentFile" type="file" />
          </s:decorate>
     </div>
     <div id="attachmentModalSubmit" class="modalSubmit">
          <h:commandButton id="attachmentSubmitButton" value="#{messages['action.text.submit']}" action="#{attachmentAction.addAttachment()}" onclick="attachmentSubmit();" />
          <button id="attachmentCancelButton" type="button" value="#{messages['action.text.cancel']}" onclick="window.parent.hideAttachmentModal();">#{messages['action.text.cancel']}</button>
     </div>
     <input type="hidden" name="cid" value="#{conversation.id}" />
</h:form>

Here is the filter that overrides Seam's multipart filter. 这是覆盖Seam多部分过滤器的过滤器。

package XXXXXXXXXXXXX.attachment;  

import java.io.File;  
import java.io.IOException;  
import java.rmi.server.UID;  
import java.util.HashMap;  
import java.util.List;  
import java.util.Map;  

import javax.servlet.FilterChain;  
import javax.servlet.ServletException;  
import javax.servlet.ServletRequest;  
import javax.servlet.ServletResponse;  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  

import org.apache.commons.fileupload.FileItem;  
import org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException;  
import org.apache.commons.fileupload.FileUploadException;  
import org.apache.commons.fileupload.disk.DiskFileItemFactory;  
import org.apache.commons.fileupload.servlet.ServletFileUpload;  
import org.jboss.seam.ScopeType;  
import org.jboss.seam.annotations.Install;  
import org.jboss.seam.annotations.Name;  
import org.jboss.seam.annotations.Scope;  
import org.jboss.seam.annotations.intercept.BypassInterceptors;  
import org.jboss.seam.annotations.web.Filter;  
import org.jboss.seam.web.AbstractFilter;  

/** 
* This filter is used to override Seam's multipart filter so that we 
* can have multiple temporary files on the server cued and ready to 
* go to XXXXXXXXX. It uses the Apache Commons FileUpload objects to 
* handle the parsing of the request and the temporary files. 
* 
*/  
@Scope(ScopeType.APPLICATION)  
@Name("org.jboss.seam.web.multipartFilter")  
@Install(precedence = Install.APPLICATION)  
@BypassInterceptors  
@Filter(within={"org.jboss.seam.web.ajax4jsfFilter", "org.jboss.seam.web.exceptionFilter"})  
public class MEDWareMultipartFilter extends AbstractFilter {  

    // This is unused, we always want temp files since we are caching before upload to XXXXXXXXX.  
    // Leaving it in to mirror Seam's multipart filter, in case it gets set from the components.xml.  
    @SuppressWarnings("unused") private boolean createTempFiles = true;  
    private int maxRequestSize = -1;  
    private String acceptedFileExtensions = "txt,pdf,doc,docx,xls,xlsx";  

    public void setCreateTempFiles(boolean createTempFiles) { }  

    public void setMaxRequestSize(int maxFileSize) {  
        this.maxRequestSize = maxFileSize;  
    }  

    public String getAcceptedFileExtensions() {  
        return acceptedFileExtensions;  
    }  

    public void setAcceptedFileExtensions(String acceptedFileExtensions) {  
        this.acceptedFileExtensions = acceptedFileExtensions;  
    }  

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {  

        if (!(response instanceof HttpServletResponse)) {  
            chain.doFilter(request, response);  
            return;  
        }  

        HttpServletRequest httpRequest = (HttpServletRequest) request;  

        if (ServletFileUpload.isMultipartContent(httpRequest)) {  
            File repository = (File) this.getServletContext().getAttribute("javax.servlet.context.tempdir");  
            DiskFileItemFactory factory = new DiskFileItemFactory(0, repository);  
            ServletFileUpload upload = new ServletFileUpload(factory);  
            upload.setSizeMax(maxRequestSize);  

            List<FileItem> formItems = null;  

            try {  
                formItems = upload.parseRequest(httpRequest);  
            } catch (SizeLimitExceededException slee) {  
                throw new org.jboss.seam.web.FileUploadException("File size excededs maximum allowed.", slee);  
            } catch (FileUploadException fue) {  
                throw new org.jboss.seam.web.FileUploadException("Error uploading file.", fue);  
            }  

            Map<String, String> parameters = new HashMap<String, String>();  
            Map<String, File> fileParameters = new HashMap<String, File>();  

            if (formItems != null && formItems.size() > 0) {  
                for (FileItem item : formItems) {  
                    if (item.isFormField()) {  
                        parameters.put(item.getFieldName(), item.getString());  
                    } else {  
                        String fileName = item.getName();  

                        // This is for IE7 (and Safari?) which sends the whole path.  
                        fileName = fileName.substring(fileName.lastIndexOf("\\") + 1);  

                        if (!MyMultipartRequestUtils.isValidFileType(acceptedFileExtensions, fileName)) {  
                            throw new org.jboss.seam.web.FileUploadException("The file type is not an accepted file type.");  
                        }  

                        File tempFile = null;  
                        try {  
                            tempFile = File.createTempFile(new UID().toString().replace(":", "-"), ".upload");  
                            tempFile.deleteOnExit();  
                            item.write(tempFile);  
                        } catch (Exception e) {  
                            throw new org.jboss.seam.web.FileUploadException("Error uploading file. Could not write file to server.");  
                        }  
                        fileParameters.put(fileName, tempFile);  
                    }  
                }  
            }  
            MyMultipartRequestWrapper requestWrapper = new MyMultipartRequestWrapper(httpRequest, parameters, fileParameters);  
            chain.doFilter(requestWrapper, response);  
        } else {  
            chain.doFilter(request, response);  
        }  
    }  

}  

So, to reiterate, if I use the frame to upload files, everything works and the frame continues on the same conversation adding each child to the parent, if I upload a file that is too big, I get the correct message in the global message area of the frame, but the conversation get incremented and then the children are obviously being added to a new parent entity in the new conversation. 因此,重申一下,如果我使用框架上传文件,那么一切正常,框架继续进行相同的对话,将每个孩子添加到父级,如果我上传的文件太大,则会在全局消息中得到正确的消息框的最大面积,但是对话会增加,然后显然会将子级添加到新对话中的新父实体中。 Any help would be greatly appreciated. 任何帮助将不胜感激。

I just ended up adding a field to my custom request wrapper to carry any exceptions I wanted to handle and then handled them in the 我刚刚在自定义请求包装器中添加了一个字段,以携带要处理的所有异常,然后在

#{attachmentAction.addAttachment()}

action call further up the request chain. 动作调用进一步拉高了请求链。 All works now, I just add my faces messages from there and the conversation does not get incremented the same as if I had a successful upload. 现在一切正常,我只是从那里添加我的面孔消息,并且对话没有像我成功上传一样增加。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM