Webapp behaves as expected when run from eclipse while when exported as war fails

懵懂的女人 提交于 2019-12-25 08:17:52

问题


This has been driving me nuts.

So I have a (very simple vanilla servlet 3) web app. When I run it in eclipse all is fine. Among others I am able to register an account with Unicode (greek) username and then log in as site admin and visit the user's profile alright. When I export war to $CATALINA_HOME\webapps, launch $CATALINA_HOME\bin\startup.bat, open the site in the browser, login as admin and try to visit the user profile the username etc display as blank.
The files in ...\apache-tomcat-7.0.32\conf and the ones in ...\eclipse_workspaces\javaEE\Servers\Tomcat v7.0 Server at localhost-config differ only in the line (in server.xml) :

<Context docBase="ted2012" path="/ted2012" reloadable="true" 
source="org.eclipse.jst.jee.server:ted2012"/>

which is an eclipse thing.

The doGet method (slimmed) in the profile servlet :

protected void doGet(HttpServletRequest request,
        HttpServletResponse response) throws ServletException, IOException {

    final String username = Helpers.decodeRequest(request
            .getParameter("user"));
    if (username != null) {
        User user = null;
        try {
            System.out
                    .println("ProfileController.doGet() user name DECODED : "
                            + username);
            user = userService.getUserWithUsername(username); // THIS FAILS
            System.out.println("ProfileController.doGet() user : " + user);
            request.setAttribute("userToShow", user);
        } catch (ServiceExDBFailure e) {
            log.debug("ProfileController::doGet", e);
            request.setAttribute("ErrorString", e.getMessage());
        }
        sc.getRequestDispatcher(OTHERPROFILE_JSP)
                .forward(request, response);
        return;
    } else {
        //does not apply
    }
}

The decode method is :

public static String decodeRequest(String parameter)
        throws UnsupportedEncodingException {
    if (parameter == null)
        return null;
    System.out.println("decode - request.getBytes(\"iso-8859-1\"):"
            + new String(parameter.getBytes("iso-8859-1")));
    System.out.println("decode - request.getBytes(\"iso-8859-1\") BYTES:"
            + parameter.getBytes("iso-8859-1"));
    for (byte iterable_element : parameter.getBytes("iso-8859-1")) {
        System.out.println(iterable_element);
    }
    System.out.println("decode - request.getBytes(\"UTF-8\"):"
            + new String(parameter.getBytes(CHARSET_FOR_URL_ENCODING))); // UTF-8
    return URLDecoder.decode(new String(parameter.getBytes("iso-8859-1")),
            CHARSET_FOR_URL_ENCODING);
}

While the db call is :

            statement = conn.prepareStatement(query);
            statement.setString(1, username);
            System.out.println("ελληναρα");
            System.out.println(statement);
            set = statement.executeQuery();
            if (set.next()) {
                User user = new User();
                // user.setId(set.getInt("ID"));
                user.setUsername(set.getString("username"));
                user.setName(set.getString("name"));
                user.setSurname(set.getString("surname"));
                user.setPassword(set.getString("password"));
                user.setEmail(set.getString("email"));
                user.setRole(RolesENUM.values()[set.getInt("role")]);
                return user; // if the set is empty null is returned
            }

Tomcat prints :

decode - request.getBytes("iso-8859-1"):╧à╧â╧ä╬╡╧?╬╣╬▒
decode - request.getBytes("iso-8859-1") BYTES:[B@529b9ed
-49
-123
-49
-125
-49
-124
-50
-75
-49
-127
-50
-71
-50
-79
decode - request.getBytes("UTF-8"):├?┬à├?┬â├?┬ä├Ä┬╡├?┬?├Ä┬╣├Ä┬▒
ProfileController.doGet() user name DECODED : ╧à╧â╧ä╬╡╧?╬╣╬▒
com.mysql.jdbc.JDBC4PreparedStatement@766d7940: SELECT * FROM users WHERE username='╧à╧â╧ä╬╡╧?╬╣╬▒'
????????
ProfileController.doGet() user : null

while Eclipse prints :

decode - request.getBytes("iso-8859-1"):υστερια
decode - request.getBytes("iso-8859-1") BYTES:[B@4b6a6bdf
-49
-123
-49
-125
-49
-124
-50
-75
-49
-127
-50
-71
-50
-79
decode - request.getBytes("UTF-8"):ÏÏÏεÏια
ProfileController.doGet() user name DECODED : υστερια
com.mysql.jdbc.JDBC4PreparedStatement@37d02427: SELECT * FROM users WHERE username='υστερια'
ελληναρα
ProfileController.doGet() user : com.ted.domain.User@63144ceb

I believe for some reason the query that gets to the db is something crazy - notice that where in eclipse prints ελληναρα in tomcat prints ???????? while the unicode username (υστερια) prints as ╧à╧â╧ä╬╡╧?╬╣╬▒ and not as ???????.

So the question is - what changes between the Eclipse deployment and the tomcat deployment ? Why the hell the DB returns null ? I have really really tried to debug this in vain

Help

EDIT : replacing the line statement.setString(1, username); with statement.setString(1, "υστερια"); there is NO failure. So by the time this line is run the bytes are mangled up - notice though that the bytes are the same one by one

EDIT2 : Tomcat v7.0 Server at localhost Eclipse launch VM args (split for readability) :

-Dcatalina.base="C:\Dropbox\eclipse_workspaces\javaEE\.metadata\.plugins
\org.eclipse.wst.server.core\tmp1" 
-Dcatalina.home="C:\_\apache-tomcat-7.0.32" 
-Dwtp.deploy="C:\Dropbox\eclipse_workspaces\javaEE\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps" 
-Djava.endorsed.dirs="C:\_\apache-tomcat-7.0.32\endorsed"

NB : the launch for the app is created dynamically

EDIT 2013.03.30 : this is now on github - and see my more general question here


回答1:


This was finally answered here.

The gist of the answer is that I eclipse had as default encoding UTF-8 and Tomcat windows-1252 so when I call new String() without specifying the encoding those are used to tranlate the byte[] to chars. Doing

new String(parameter.getBytes("iso-8859-1"), "UTF-8");

solves the problem - it would not though if tomcat in

request.getParameter("user") // url decoding is performed by tomcat - using the
// URIEncoding from server.xml or by default ISO-8859

would not use by default ISO-8859 as another encoding (say ASCII) would probably (behavior undefined and not controllable before Java 7 nio) replace undecodable characters with ? so parameter String would be corrupted (see ISO-8859-1 encoding and binary data preservation).

So bravo to tomcat for performing the conversion by default with ISO-8859 in its request.getParameter() and boo to Java ee spec guys who do not even mention in the docs that getParameter will perform URL decoding, let alone letting us specify the encoding, overriding server.xml.



来源:https://stackoverflow.com/questions/14914983/webapp-behaves-as-expected-when-run-from-eclipse-while-when-exported-as-war-fail

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!