Why Primefaces change encoding of the response? - jsf

I have a webapp that uses Primefaces 4 (I cannot update it, it does not deppend on me) with a datatable with a column that sometimes has alphas (the greek letter: α).
To load this datatable, I use a button of a form with some filters. When I click on that button, the backend sends me the response using ISO-8859-15 encoding. That is a problem because with this encoding alphas are represented as a question mark (?) but, when I use the pagination buttons to go to the second page, I receive the response using UTF-8 encoding and alphas are correctly represented, even I can go back to the first page, and I receive the response using UTF-8.
I was able to solve this issue on my local testing Tomcat server changing encoding in the first line of the xhtml file:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
But this is not working in the production server that uses Weblogic 12c. The data of the datatable came from a lazydatamodel class and following it with the debugger it does exactly the same with both buttons, except for the page obviously. But I leave here the code of the load method of this lazydatamodel class:
private List<ListElement> data;
#Autowired
private transient CamFacade camFacade;
public List<ListElement> load(int first, int pageSize, String sortField,
SortOrder sortOrder, Map<String, String> filters) {
Map<String, Object> params = new HashMap<String, Object>();
params.putAll(filters);
params.put("first", first);
params.put("pageSize", pageSize);
if(sortField == null){
params.put("orderBy", params.get("orderBy"));
params.put("order", params.get("order"));
}else{
params.put("orderBy", sortField);
params.put("order", sortOrder.name());
}
int count = camFacade.countByParams(params);
if (count > 0 ) {
data = camFacade.findByParams(params);
} else {
data = new ArrayList<ListElement>();
}
return data;
}
EDIT:
I also tried this solution: Unicode input retrieved via PrimeFaces input components become corrupted
But it does not work for me. If I am not misunderstanding it, with this code I change the request encoding, but actually my request is ok, it is UTF-8. I need to change the RESPONSE encoding.
Any idea how to solve this problem?

You can add a Filter where you set the character encoding on both the request and the response to UTF-8:
#WebFilter("/*")
public class CharacterEncodingFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
request.setCharacterEncoding(StandardCharsets.UTF_8.name());
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
chain.doFilter(request, response);
}
// ...
}

Related

Custom renderer for Radio Group / SelectOne does nothing

The XPages renderer for a radio group put everything into tables and is basically terrible. I'm trying to fix this with a custom renderer. I've tried a lot of things but right now I'm stuck because I simply have no information to go further.
My renderer is declared in faces-config like so:
<renderer>
<component-family>javax.faces.SelectOne</component-family>
<renderer-type>itd.alcs.controller.Radio</renderer-type>
<renderer-class>itd.alcs.controller.RadioGroupRenderer</renderer-class>
</renderer>
<renderer>
<component-family>javax.faces.Input</component-family>
<renderer-type>itd.alcs.controller.Radio</renderer-type>
<renderer-class>itd.alcs.controller.RadioGroupRenderer</renderer-class>
</renderer>
My renderer code is:
public class RadioGroupRenderer extends com.ibm.xsp.renderkit.html_basic.RadioRenderer {
public RadioGroupRenderer() {
System.out.println("RadioGroupRenderer");
}
#Override
public void encodeBegin(FacesContext context, UIComponent component) throws IOException {
System.out.println("encodeBegin");
super.encodeBegin(context, component);
}
#Override
public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
System.out.println("encodeEnd");
Writer writer = context.getResponseWriter();
XspSelectOneRadio tcomponent = component instanceof XspSelectOneRadio ? (XspSelectOneRadio) component : null;
if (tcomponent == null) {
System.out.println("Nothing");
writer.write("Nothing");
}
if (tcomponent.isReadonly()) {
// writer.write(tcomponent.getValue().toString());
System.out.println("Read Only");
writer.write("Read Only");
} else {
//super.encodeEnd(context, component);
System.out.println("Edit");
writer.write("Edit");
}
}
}
Something is happening when I apply this renderer-type. And that something is that I get no output. Nothing in my response. No errors in the console. None of the console messages I put in in the constructor or encodeBegin or encodeEnd.
If I change the name of the renderer-type or renderer-class to something invalid... still nothing. No errors, no output. I don't know if something is trapping my error and handling them silently or.... what?
How can I figure out what I'm doing wrong here? Bonus points if you can TELL me what I'm doing wrong, but what I really want to know is how to get some sort of feedback to troubleshoot this myself.
Answering my own question in case anyone else runs into this....
The <renderer>...</renderer> tags need to go inside <render-kit></render-kit> tags. You'd think I'd have come across that in 4 hours of searching, but no.

REST-like URL rewriting with natural conversation concept

There used to be a concept of natural conversation in seam. basically the conversation id could be custom, ie. someAction:100, and this could be associated with a restlike url for a conversation. hence the url would be something like:
http:localhost:8080/some_context/someAction:100
I am failing to find the alternative in standard JSF. How do you do it?
Please help as I am in a desperate situation. at least let me know if there is any literature, or if it could be achieved by deltaspike.
Many Thanks
You can do it with DeltaSpike - just inject WindowContext and use/restore whatever window-id you like via the method activateWindow. Afterwards the conversation-scope provided by DeltaSpike (#GroupedConversationScoped) can be used without any further initialization as described in the documentation.
If you have e.g. a JSF application in combination with the JSF-module of DeltaSpike which renders the window-id as 'dswid', you can use the following Servlet-Filter to restore and activate the same window for any Servlet-based technology like JAX-RS,... (don't forget the mapping for the Servlet-Filter).
With JSF don't forget to add the tag to your page-template (as described in the documentation). If you need to create a manual link you can get the current window-id via:
dswid=#{dsWindowContext.currentWindowId}
If you don't like to use 'dswid', just use and extract the information as with any other custom parameter (or use a lib like prettyfaces/rewrite).
If you don't use JSF, you need to render the window-id on your own and ensure that it gets sent back to the server as request-parameter (as with any other parameter you are using).
In your code which finally handles the request, you can just inject any grouped-conversation-scoped bean (or do a lookup via BeanProvider).
public class WindowIdFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
String windowId = request.getParameter("dswid");
if (windowId != null) {
WindowContext windowContext = BeanProvider.getContextualReference(WindowContext.class);
windowContext.activateWindow(windowId);
}
chain.doFilter(request, response);
}
#Override
public void destroy() {
}
}

How to save all FacesMessages over different requests

I was just wondering to implement a kind of log display to user where in all messages in the application are displayed to user all the time.
Since I use JSF 1.2 and RF 3.3.3, wanted to know if it is possible to save all messages be it added by different requests and display them to user, so that user will know the history of actions he has done. It is also useful for support team to analyse the cause of the problem and he can send the messages to developer if it needs to simulated or to debug purpose also.
I also know facesmessages get cleared over different requests, thats where my question lies, to save messages over different requests :)
Could be handled in different ways by saving them is a session variable or so...I would appreciate all possible answers
You could collect all messages during the render response in a PhaseListener. E.g.
public class MessagesListener implements PhaseListener {
#Override
public PhaseId getPhaseId() {
return PhaseId.RENDER_RESPONSE;
}
#Override
public void beforePhase(PhaseEvent event) {
FacesContext context = event.getFacesContext();
Iterator<String> clientIds = context.getClientIdsWithMessages();
while (clientIds.hasNext()) {
String clientId = clientIds.next();
Iterator<FacesMessage> messages = context.getMessages(clientId);
while (messages.hasNext()) {
FacesMessage message = messages.next();
save(clientId, message); // Do your job here.
}
}
}
#Override
public void afterPhase(PhaseEvent event) {
// NOOP.
}
}
To get it to run, register it as follows in faces-config.xml:
<lifecycle>
<phase-listener>com.example.MessagesListener</phase-listener>
</lifecycle>

Is it possible to extract text by page for word/pdf files using Apache Tika?

All the documentation I can find seems to suggest I can only extract the entire file's content. But I need to extract pages individually. Do I need to write my own parser for that? Is there some obvious method that I am missing?
Actually Tika does handle pages (at least in pdf) by sending elements <div><p> before page starts and </p></div> after page ends. You can easily setup page count in your handler using this (just counting pages using only <p>):
public abstract class MyContentHandler implements ContentHandler {
private String pageTag = "p";
protected int pageNumber = 0;
...
#Override
public void startElement (String uri, String localName, String qName, Attributes atts) throws SAXException {
if (pageTag.equals(qName)) {
startPage();
}
}
#Override
public void endElement (String uri, String localName, String qName) throws SAXException {
if (pageTag.equals(qName)) {
endPage();
}
}
protected void startPage() throws SAXException {
pageNumber++;
}
protected void endPage() throws SAXException {
return;
}
...
}
When doing this with pdf you may run into the problem when parser doesn't send text lines in proper order - see Extracting text from PDF files with Apache Tika 0.9 (and PDFBox under the hood) on how to handle this.
You'll need to work with the underlying libraries - Tika doesn't do anything at the page level.
For PDF files, PDFBox should be able to give you some page stuff. For Word, HWPF and XWPF from Apache POI don't really do page level things - the page breaks aren't stored in the file, but instead need to be calculated on the fly based on the text + fonts + page size...
You can get the number of pages in a Pdf using the metadata object's xmpTPg:NPages key as in the following:
Parser parser = new AutoDetectParser();
Metadata metadata = new Metadata();
ParseContext parseContext = new ParseContext();
parser.parse(fis, handler, metadata, parseContext);
metadata.get("xmpTPg:NPages");

How to handle HTTP 403 with Spring Security 3.0.x

I'm facing a little issue with Spring Security 3.0.x (3.0.2 in particular at the moment). The whole application I'm working on is working perfectly except when someone who doesn't have the authorities tries to log on.
When it occurs, the users is redirected to the "welcome" page, since his username/password are valid, and he receive a cute white page with this : "Error 403: Access is denied"
So, I've been looking on the net trying to find how this behavior can be handled. So far I've come to the conclusion, please correct me if I'm wrong, that it is managed by the ExceptionTranslationFilter. But I don't quite understand how to make any good use of this information.
I've tryied to edit my SecurityContext.xml to add a access-denied-handler tag to my http tag, but it doesn't work. Do I need to add more than this tag to make it work? Is there any other possibilities to make my application more user-friendly?
Edit : I would like to redirect to a page, let's says 403.html, for example.
Sincerly,
Thanks
I still don't get why you had to implement your own access handler... I have currently faced same task:
<security:access-denied-handler error-page="/accessDenied"/> - works like charm.
Don't forget to specify handler in your Controller:
#RequestMapping(value = "/accessDenied")
public String accessDenied() {
return "accessDenied"; // logical view name
}
Update for Spring Boot(2014 Oct):
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.exceptionHandling().accessDeniedHandler(customHandler) OR .accessDeniedPage("/somePage.html").and
.formLogin()
.failureHandler(ajaxAuthenticationFailureHandler)}
Nowadays we don't really return views for such task since angular js kicks in so you can use your failure/success handler and return tailored JSON responses. For us it was sufficient to use failure handler but you get to choose where you want your control to kick in. We generally don't use view resolvers as there are UI tiles frameworks(such as angular partials) able to construct pieces into single page for you. Html pieces are stored on the server and served simply as static resources.
Lets play with Embedded Tomcat to achieve similar behavior to web.xml !
#Configuration
#EnableAutoConfiguration
public class ApplicationWebXml extends SpringBootServletInitializer {
private static final Logger LOGGER = LoggerFactory.getLogger(Application.class);
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.profiles(addDefaultProfile())
.showBanner(false)
.sources(Application.class);
}
//required for container customizer to work, the numerous tutorials didn't work for me, so I simply tried overriding the default one
#Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
return tomcat;
}
#Bean
public EmbeddedServletContainerCustomizer containerCustomizer(
) {
return new EmbeddedServletContainerCustomizer() {
#Override
public void customize(ConfigurableEmbeddedServletContainer container) {
TomcatEmbeddedServletContainerFactory containerFactory = (TomcatEmbeddedServletContainerFactory) container;
containerFactory.setSessionTimeout(1); // just for your interest, remove as necessary
containerFactory.addErrorPages(new ErrorPage(HttpStatus.FORBIDDEN,"/views/accessDenied.html"),
new ErrorPage(HttpStatus.NOT_FOUND,"/views/notFound.html"));
containerFactory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
#Override
public void customize(Connector connector) {
connector.setPort(8082);// just for your interest, remove as necessary
}
});
}
};
}
}
A cleaner way to handle error redirects is to use the <error-page> and <error-code> tags in your web.xml. See below for an example:
<!-- Custom 403 Error Page -->
<!--
NOTE: Security will throw this error when a user has been authenticated successfully
but lacks the permissions to perform the requested action.
-->
<error-page>
<error-code>403</error-code>
<location>/403.jsp</location>
</error-page>
This block of code will redirect to the specified location whenever it encounters the specified error code.
This eliminates the need for authorization code inside your application logic.
I've found how to do this. By implementing the AccessDeniedHandler interface and the corresponding handle method I can, easily, control the way the Http 403 error is handled.
This way, you can add various items in the session and then intercept them on your jsp.
The xml file then looks like this :
<sec:http>
<!-- lots of urls here -->
<sec:access-denied-handler ref="accessDeniedHandler" />
<sec:anonymous/>
</sec:http>
<bean id="accessDeniedHandler" class="foo.bar.CustomAccessDeniedHandler">
<property name="accessDeniedUrl" value="403.html" />
</bean>
The java class :
package foo.bar;
public class CustomAccessDeniedHandler implements org.springframework.security.web.access.AccessDeniedHandler {
private String accessDeniedUrl;
public CustomAccessDeniedHandler() {
}
public CustomAccessDeniedHandler(String accessDeniedUrl) {
this.accessDeniedUrl = accessDeniedUrl;
}
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
response.sendRedirect(accessDeniedUrl);
request.getSession().setAttribute("CustomSessionAttribute", "value here");
}
public String getAccessDeniedUrl() {
return accessDeniedUrl;
}
public void setAccessDeniedUrl(String accessDeniedUrl) {
this.accessDeniedUrl = accessDeniedUrl;
}
}
And a jsp example :
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:if test="${!empty CustomSessionAttribute}">
<br/>
ACCESS IS DENIED
<br/>
</c:if>
<!-- other stuff down here -->
The way to make this work is to define a handler in your entry point:
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
#Override
public void commence(HttpServletRequest request, HttpServletResponse response, org.springframework.security.core.AuthenticationException authException) throws IOException, ServletException {
if (authException != null) {
// you can check for the spefic exception here and redirect like this
response.sendRedirect("403.html");
}
}
}
You can define this as your entry point by setting this as you entry point in the xml config file:
<http entry-point-ref="customAuthenticationEntryPoint">
...
</http>
You have checked the tag in an application and to me it seems to work.
<sec:access-denied-handler error-page="/handle403Url" />
where handle403Url I want to call to handle this error (for example to show an error).
Don't forget that you have to allow this url in the filters so it can be reached by this user authority, so in the start of the flters you have to add something like this:
<sec:intercept-url pattern="/handle403Url" filters="none" />

Resources