Incompatibilidades MyFaces Tomahawk e RichFaces 3.2
Marcos Sousa | April 28, 2008Quem usa os componentes do Myfaces Tomahawk e RichFaces em um mesmo projeto, poderá ter problemas ao atualizar a versão do RichFaces para a versão 3.2. O problema é que a versão 3.2 tem um componente de upload em ajax que requer algumas funcionalidades extras que foram adicionadas ao filtro do RichFaces. Porém estas configurações entram em conflito com as funcionalidades do Filtro de extensão do Myfaces.
Os conflitos gerados impedem o funcionamento apenas dos componentes de upload de ambos os casos. Isto porque ambos criam um objeto para adaptar a requisição que envolve envio de arquivos (enctype=”multipart/form-data”). Vi em alguns fóruns de discussão do RichFaces que a maneira de contornar o problema seria alterar a ordem de declaração dos filtros, porém para alguns tipos de requisições esta solução não resolve.
Uma forma de resolver a incompatibilidade é sobrescrever um dos dois filtros e anular a funcionalidade de upload, é uma solução temporária que irá anular o funcionamento do componente de uploads do filtro sobrescrito. O exemplo abaixo reimplementa o filtro do Tomahawk:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | package com.marcossousa.filters.myfaces; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.myfaces.renderkit.html.util.AddResource; import org.apache.myfaces.renderkit.html.util.AddResourceFactory; import org.apache.myfaces.webapp.filter.ExtensionsResponseWrapper; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * Override para evitar problemas de inconsistência dos filtros do RichFaces e Tomahawk. */ public class ExtensionsFilter implements Filter { private Log log = LogFactory.getLog(ExtensionsFilter.class); private int _uploadMaxFileSize = 100 * 1024 * 1024; // 10 MB private int _uploadThresholdSize = 1 * 1024 * 1024; // 1 MB private String _uploadRepositoryPath = null; //standard temp directory private ServletContext _servletContext; public static final String DOFILTER_CALLED = "org.apache.myfaces.component.html.util.ExtensionFilter.doFilterCalled"; /** * Init method for this filter */ public void init(FilterConfig filterConfig) { String param = filterConfig.getInitParameter("uploadMaxFileSize"); _uploadMaxFileSize = resolveSize(param, _uploadMaxFileSize); param = filterConfig.getInitParameter("uploadThresholdSize"); _uploadThresholdSize = resolveSize(param, _uploadThresholdSize); _uploadRepositoryPath = filterConfig.getInitParameter("uploadRepositoryPath"); _servletContext = filterConfig.getServletContext(); } private int resolveSize(String param, int defaultValue) { int numberParam = defaultValue; if (param != null) { param = param.toLowerCase(); int factor = 1; String number = param; if (param.endsWith("g")) { factor = 1024 * 1024 * 1024; number = param.substring(0, param.length() - 1); } else if (param.endsWith("m")) { factor = 1024 * 1024; number = param.substring(0, param.length() - 1); } else if (param.endsWith("k")) { factor = 1024; number = param.substring(0, param.length() - 1); } numberParam = Integer.parseInt(number) * factor; } return numberParam; } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if(request.getAttribute(DOFILTER_CALLED)!=null) { chain.doFilter(request, response); return; } request.setAttribute(DOFILTER_CALLED,"true"); if (!(response instanceof HttpServletResponse)) { chain.doFilter(request, response); return; } HttpServletResponse httpResponse = (HttpServletResponse) response; HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletRequest extendedRequest = httpRequest; // Serve resources AddResource addResource; try { addResource=AddResourceFactory.getInstance(httpRequest); if( addResource.isResourceUri(_servletContext, httpRequest ) ){ addResource.serveResource(_servletContext, httpRequest, httpResponse); return; } } catch(Throwable th) { log.error("Exception wile retrieving addResource",th); throw new ServletException(th); } try { addResource.responseStarted(); if (addResource.requiresBuffer()) { ExtensionsResponseWrapper extendedResponse = new ExtensionsResponseWrapper((HttpServletResponse) response); // Standard request chain.doFilter(extendedRequest, extendedResponse); extendedResponse.finishResponse(); // write the javascript stuff for myfaces and headerInfo, if needed HttpServletResponse servletResponse = (HttpServletResponse)response; // only parse HTML responses if (extendedResponse.getContentType() != null && isValidContentType(extendedResponse.getContentType())) { addResource.parseResponse(extendedRequest, extendedResponse.toString(), servletResponse); addResource.writeMyFacesJavascriptBeforeBodyEnd(extendedRequest, servletResponse); if( ! addResource.hasHeaderBeginInfos() ){ // writes the response if no header info is needed addResource.writeResponse(extendedRequest, servletResponse); return; } // Some headerInfo has to be added addResource.writeWithFullHeader(extendedRequest, servletResponse); // writes the response addResource.writeResponse(extendedRequest, servletResponse); } else { byte[] responseArray = extendedResponse.getBytes(); if(responseArray.length > 0) { // When not filtering due to not valid content-type, deliver the byte-array instead of a charset-converted string. // Otherwise a binary stream gets corrupted. servletResponse.getOutputStream().write(responseArray); } } } else { chain.doFilter(extendedRequest, response); } } finally { addResource.responseFinished(); } } public boolean isValidContentType(String contentType) { return contentType.startsWith("text/html") || contentType.startsWith("text/xml") || contentType.startsWith("application/xhtml+xml") || contentType.startsWith("application/xml"); } /** * Destroy method for this filter */ public void destroy() { // NoOp } } |
Porém, uma forma eficaz de resolver o problema é a criação de um parâmetro para identificar qual componente de upload está sendo usado e o filtro trataria a criação ou não do objeto de adaptação o que acabaria com as incompatibilidades. Já fiz a requisição do JIRA, agora é aguardar as correções.





