Showing posts with label JBoss. Show all posts
Showing posts with label JBoss. Show all posts

Monday, October 14, 2013

Hot Deployment with IntelliJ IDEA

Recently there was a voting in the PrimeFaces forum PrimeFaces IDE Poll for the best IDE used to develop PrimeFaces applications. The most people voted for NetBeans. NetBeans and Eclipse are free IDEs. My favorite IDE IntelliJ IDEA Ultimate is not free and I think this is a reason why there are less people using it on the job. I thought it would be a good idea to show some nice features in IntelliJ. This post will demonstrate how to configure IntelliJ for the hot deployment when developing web projects. Hot deployment means you can change web resources or classes at runtime and the changes will be recognized immediately without server restart. An useful feature during development process. In the example, I will take the application server JBoss 7, but any other server can be configured in the same manner as well. A good introduction to IntelliJ and JBoss there is in the IntelliJ Wiki. For a general information regarding working with application servers in IntelliJ please refer this help page.

We assume, the application server is already configured. The next step is to configure an exploded WAR artifact for the web project. An exploded WAR is a decompressed web application archive, a directory structure that is ready for deployment on an application server. IntelliJ creates it automatically, but nevertheless, you should go to File --> Project Structure --> Artefacts and ensure that the exploded web application ends with the extension .war. If you use Maven, the exploded WAR is created below the target folder. More info on the help page.


You should also check if the Hot Swap is enabled. Go to the File --> Settings --> Debugger --> HotSwap and ensure that all checkboxes are checked and the radio button "Reload classes after compilation" is set to "Always".


As next step, click on the "Edit Configurations..." and go to the configured server. In the "Run/Debug Configurations" dialog, select "Update resources" in the drop-down "On frame deactivation". That means, when you switch to the browser, IntelliJ will copy resource files (JavaScript, CSS) from the source location (src/main/webapp) to the directory where it builds the exploded WAR to deploy.


Hot deployment for changed Java classes is resticted by JVM. E.g. the hot deployment for classes with changed method signature(s) doesn't work. But if you changed a method body, it will work. So, if you don't use JRebel which allows the hot deployment for classes being structurally modified, you can still rely on IntelliJ. All what you need to do for changes in Java classes is to recompile them. For that, you can go to the menu Build --> Compile or simple hit Ctrl + Shift + F9. After that, go to the browser and refresh the page to see changes.


Tuesday, July 2, 2013

Proper decoding of URL parameters on the server-side in JBoss

I spent many hours today to figure out how to force a proper decoding of encoded characters in JSF applications running on JBoss (using JBoss 7 Final). The problem occurs when you have e.g. chinese characters passed through URL. Assume you have 指事, encoded as %E6%8C%87%E4%BA%8B. Surprise, but these characters arrive you on the server-side as 指事. They are decoded by server automatically with ISO-8859-1. So, it doesn't matter if you try to decode it by yourself like
FacesContext fc = FacesContext.getCurrentInstance();
String param = fc.getExternalContext().getRequestParameterMap().get(name);
String decodedParam = java.net.URLDecoder.decode(param, "UTF-8");
It doesn't help because characters were already wrong decoded and you get them already wrong decoded from the request parameter map. It doesn't help too if you have on the page
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
To overcome this bug you need two things: a special character encoding filter and a configuration in JBoss' standalone.xml. The filter should set the configured encoding for both request and response.
public class CharacterEncodingFilter implements Filter {

    /** The default character encoding to set for request / response. */
    private String encoding = null;

    /** The filter configuration object. */
    private FilterConfig filterConfig;

    /** Should a character encoding specified by the client be ignored? */
    private boolean ignore = true;

    public void destroy() {
        encoding = null;
        filterConfig = null;
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
        ServletException {
        // conditionally select and set the character encoding to be used
        if ((ignore || (request.getCharacterEncoding() == null)) && (encoding != null)) {
            request.setCharacterEncoding(encoding);
            response.setCharacterEncoding(encoding);
        }

        // pass control on to the next filter
        chain.doFilter(request, response);
    }

    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
        this.encoding = filterConfig.getInitParameter("encoding");

        String value = filterConfig.getInitParameter("ignore");

        this.ignore = ((value == null) || value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes"));
    }
}
Note: It will not help if you only set the encoding for request. You should also set it for response by response.setCharacterEncoding(encoding). Configuration in web.xml looks like
<filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>xyz.mypackage.CharacterEncodingFilter</filter-class>
    <init-param>
        <description>override any encodings from client</description>
        <param-name>ignore</param-name>
        <param-value>true</param-value>
    </init-param>
    <init-param>
        <description>the encoding to use</description>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>*.jsf</url-pattern>
</filter-mapping>
Now you have to add following system properties to the standalone.xml, direct after the closing <extensions> tag:
<system-properties>
    <property name="org.apache.catalina.connector.URI_ENCODING" value="UTF-8"/>
    <property name="org.apache.catalina.connector.USE_BODY_ENCODING_FOR_QUERY_STRING" value="true"/>
</system-properties>
From the docu:
  • org.apache.catalina.connector.URI_ENCODING specifies the character encoding used to decode the URI bytes, after %xx decoding the URL. If not specified, ISO-8859-1 will be used.
  • org.apache.catalina.connector.USE_BODY_ENCODING_FOR_QUERY_STRING specifies if the encoding specified in contentType should be used for URI query parameters, instead of using the org.apache.catalina.connector.URI_ENCODING. This setting is present for compatibility with Tomcat 4.1.x, where the encoding specified in the contentType, or explicitely set using Request.setCharacterEncoding method was also used for the parameters from the URL. The default value is false.
JBoss looks now set character encoding for response and decodes URL parameters with it. I hope this info will help you to save your time.