edwin

A java.lang.IllegalArgumentException when Using SpringMVC @PathVariable

Another exception happened to me today while im deploying my application to Tomcat 7, somehow the error (again) never happen on my IDE. The error is related to Spring MVC’s @PathVariable. Below is the complete stacktrace for the error.

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalArgumentException: Name for argument type [java.lang.String] not available, and parameter name information not found in class file either.
	org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:894)
	org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
	com.opensymphony.module.sitemesh.filter.PageFilter.parsePage(PageFilter.java:119)
	com.opensymphony.module.sitemesh.filter.PageFilter.doFilter(PageFilter.java:55)
	org.springframework.security.web.FilterChainProxy$VirtualFilterChain .doFilter(FilterChainProxy.java:330)
	org.springframework.security.web.access.intercept.FilterSecurityInterceptor .invoke(FilterSecurityInterceptor.java:118)
	org.springframework.security.web.access.intercept.FilterSecurityInterceptor .doFilter(FilterSecurityInterceptor.java:84)

And this is the suspected method which raise exception,

    @RequestMapping(value ="/baculsoft/news/view/{id}", method = RequestMethod.GET)
    public String newsView(ModelMap modelMap, 
                        @PathVariable String id) {
        modelMap.put("news", newsService.get(id);
        return "news/view";
    }

The workaround is actually simple, below is how to deal with it,

    @RequestMapping(value ="/baculsoft/news/view/{id}", method = RequestMethod.GET)
    public String newsView(ModelMap modelMap, 
                        @PathVariable("id") String id) {
        modelMap.put("news", newsService.get(id);
        return "news/view";
    }

Actually very simple workaround, but since i have hundreds of methods using @PathVariable, it’s not so simple anymore. And the weird thing is, the .war exported from Eclipse IDE run perfectly, only .war created from Netbeans that raise exception. I dont know why, but somehow Netbeans’ ant create a different war compared to Eclipse’s war file.

After sometimes googling, i found out that it happens due to javac’s debug parameter on Netbeans’ ant, changing “debug” default value into “on” on Netbeans’ build-impl.xml makes my war file run perfectly on Tomcat 7. Well i hope it hepled others, cheers (B)

A Weird Exception, java.lang.IllegalArgumentException: Filter mapping specifies an unknown filter name “FilterName”

Today i found an exception while deploying my .war application to Tomcat web server for production usage, very weird because i never had this exception on my IDE before. This is the complete exception stacktrace,

Caused by: java.lang.IllegalArgumentException: Filter mapping specifies an unknown filter name FilterName
	at org.apache.catalina.core.StandardContext.addFilterMap(StandardContext.java:2506)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)

below is my web.xml content,

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="crm" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_4.xsd">
    <display-name>edw</display-name>
    <context-param>
        <param-name>edw</param-name>
        <param-value>edw</param-value>
    </context-param>
    
    <filter-mapping>
        <filter-name>FilterName</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
	
    <filter>
        <filter-name>FilterName</filter-name>
        <filter-class>com.edw.filter.FilterName</filter-class>
    </filter>
</web-app>

How to fix it is actually very simple, i only need to swap between and tag. Below is the correct web.xml.

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="crm" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_4.xsd">
    <display-name>edw</display-name>
    <context-param>
        <param-name>edw</param-name>
        <param-value>edw</param-value>
    </context-param>
    
    <filter>
        <filter-name>FilterName</filter-name>
        <filter-class>com.edw.filter.FilterName</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>FilterName</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>

Weird eh :p

How to Compress Log4J’s Log File

Today i found a very weird condition on one of my end user. Their application’s log file is so big, despite the log4j’s log level is set to INFO. Im using log4j’s DailyRollingFileAppender which would create a new log file everyday. Each file’s size is around 10 to 20MB, and i see the log files is like 3 months old. Which makes total of almost 2GBs of log files.

So my solution to them is to compress everyday’s log into gzip, gz or perhaps into zip file. Basically, im using one of log4j’s companion..

Okay, so here is my solution, first a simple pom.xml to download the libraries needed,

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.edw.compresslogfile</groupId>
    <artifactId>CompressLogFile</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>CompressLogFile</name>
    <url>http://maven.apache.org</url>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>apache-log4j-extras</artifactId>
            <version>1.0</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>                        
    </dependencies>
</project>

And then my log4j.properties file, please take a look at line 7. It will create a new log file for every second, change it into “yyyyMMdd” if you want to create a daily appender.

log4j.rootLogger=DEBUG, request

log4j.appender.request=org.apache.log4j.rolling.RollingFileAppender
log4j.appender.request.File=msg.log
log4j.appender.request.RollingPolicy=org.apache.log4j.rolling.TimeBasedRollingPolicy
log4j.appender.request.RollingPolicy.ActiveFileName =msg.log
log4j.appender.request.RollingPolicy.FileNamePattern=msg.%d{yyyyMMdd.HHmmss}.gz
log4j.appender.request.layout = org.apache.log4j.PatternLayout
log4j.appender.request.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

And my simple java test case

package com.edw.compresslogfile;

import org.apache.log4j.Logger;

/**
 * Hello world!
 *
 */
public class App {

    private static final Logger LOGGER = Logger.getLogger(App.class);

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            try {
                LOGGER.debug("Hello World " + i);
                Thread.sleep(5000);
            } catch (Exception e) {
            }
        }
    }
}

It will create a compressed log file for every second.

This is the project structure on my Netbeans,

Hope it helped others, cheers (B)

Simulate A Post Request Using Java

Today, i’ll do a simple example on how to simulate a http post request using Apache Common Http Components. This is a usefull utility, because i use it heavily on many projects, specially to do a simple messaging between desktop clients and the server side. Very simple, very lightweight and also very reliable.

Okay, first i start with the server version of the application. I create a new WebProject on Netbeans, create a simple servlet and deploy it on tomcat. This is a very simple servlet to print on netbeans console and give response whether 0 if failed, or 1 if succeed.

package com.edw.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;

public class LoginServlet extends HttpServlet {
    
    private Logger logger = Logger.getLogger(LoginServlet.class);
    
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
            String username = request.getParameter("username");
            String password = request.getParameter("password");
            
            logger.debug("receiving post " + username + " and " + password);
            response.getWriter().write("1");
        } catch (Exception e) {
            logger.error(e,e);
            response.getWriter().write("0");
        }                
    }
}

As usual, i register my servlet on web.xml.

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <servlet>
        <servlet-name>loginServlet</servlet-name>
        <servlet-class>com.edw.servlet.LoginServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>loginServlet</servlet-name>
        <url-pattern>/loginServlet</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

And now is my client’s side Java application.

package com.edw.postsimulator;

import java.util.ArrayList;
import java.util.List;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

public class PostSimulator {
    
    // this is your target url
    private static String url = "http://localhost:8084/WebTestPost/loginServlet";
    
    public static void main(String[] args) throws Exception  {
        HttpClient httpclient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(url);

        // set the parameters
        List <NameValuePair> nvps = new ArrayList<NameValuePair>();
        nvps.add(new BasicNameValuePair("username", "edwin"));
        nvps.add(new BasicNameValuePair("password", "dodol"));

        // set the encoding
        httpPost.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8));

        // send the http request and get the http response
        HttpResponse response = httpclient.execute(httpPost);
        HttpEntity resEntity = response.getEntity();
		
        // read the server's response contents
        System.out.println(EntityUtils.toString(resEntity));
    }
}

These are what is written on my Netbean’s console,

And this is my Netbean’s project configurations

Hope it helped others, Cheers :-[