移植问题及解决
By CFR(mudboy)
摘要:本文档包括将现在系统:从tomcat5移植至WAS5.1,以及从WAS5.1移植到WAS6.0的一些问题的解决过程。
1、概述
应用架构:
WebStart/jsp + struts1.1 + spring115 + hibernate2.1
2、问题及解决
2.1 症状:用了JSTL标签的JSP页面运行出错。
解决:由于was512不支持jstl2.0(标准的写法将自动使用该版本的标签而不用配置),因此,使用它时,需要web.xml中显式的增加配置,或直接写明使用:
<%@ taglib uri="/WEB-INF/tld/c-1_0.tld" prefix="c" %>
而不是2.0
在web.xml中增加如下即可
<taglib>
<taglib-uri>http://java.sun.com/jsp/jstl/core</taglib-uri>
<taglib-location>/WEB-INF/tld/c-1_0.tld</taglib-location>
</taglib>
如果支持,则可以直接用而不需要配置!
注意:jstl并不是WEB容器必须支持的东东!
2.2 症状:URLConnection调用Servlet,有两种方法设置我当前的SESSION(后端传过来的):
设置Cookie的:JSESSIONID,或重写URL,这在tomcat完全没有问题,但在WebSphere5.1下却不行,到服务器又创建了一个新的SESSION,不知道为什么?
解决:一般而言,有两种最常用的会话跟踪机制,一种就是URL重写。在客户端不接受cookie的情况下可以使用URL重写进行会话跟踪。URL重写包括向URL路径添加一些容器可以解释的数据。规范要求会话ID必须编码在URL路径中,参数名称必须是jsessionid,
例如: http://www.myserver.com/catalog/index.html;jsessionid=1234
一种就是现在最常用的cookie了,规范要求所有的servlet都必须支持cookie。容器向客户端发送一个cookie,客户端在后续的处于同一个会话的请求中向服务器返回该cookie。会话跟踪cookie的名字必须是JSESSIONID。
httpUrl=http://localhost:9080/Agile/getFlightList.do;jsessionid=-JW0T70Esp9QZlyfUKOsO7o?currentCity=PEK
上面的方式在WAS下也不行,也不知道还需要做什么设置?
原来,在WAS中,SESSIONID不止这些,而应该是:<your_session>:<websphere_clone_id>,而返回的只有:前的部分,当然没有呀!!
看下面的日志:
swt process,sessionID is :uEVqj3UC4yYmIAZvmyZzuPw
2005-06-21 13:24:06 [com.ibatis.struts.SwtAction]-[DEBUG] other:0000uEVqj3UC4yYmIAZvmyZzuPw:-1,JSESSIONID=0000uEVqj3UC4yYmIAZvmyZzuPw:-1
2005-06-21 13:24:06 [com.ibatis.struts.SwtAction]-[DEBUG] cookie:JSESSIONID=0000uEVqj3UC4yYmIAZvmyZzuPw:-1
即SESSIONID还包括冒号后的部分。
在链接页面中,将代代码做如下修改:
<%
String sessionid = "";
Cookie[] cookie = request.getCookies();
for(int i = 0; i < cookie.length; i++)
{
if(cookie[i].getName().trim().equalsIgnoreCase("JSESSIONID"))
{
sessionid = cookie[i].getValue().trim();
break;
//logger.debug("cookie:"+cookie[i].getName() + "=" +cookie[i].getValue());
}
}
%>
<a href="/Agile/swt/index.jnlp?sessionid=<%=sessionid%>">lanuch agile client here</a>
实际上,解决此方法唯一要改的地方就是链接处(见上):
但为了以后其它的兼容性,也可将URL重写也加上,这在HTTPUTIL文件中。
即不能通过调用getSession().getId()得到,而应该自己从Cookie中找
2.3 症状:ORB得不到,通过JNDI无法得到,也无法得到SUN的ORB。
解决:由于WAS用的是IBM自己改造过的JRE,因此,通过实验,无法更换到SUN的JRE,而且也无法让相关的SUN的ORB组件介入。最终还应通过JNDI获取。
将通过JNDI得到ORB的代码改成如下:
orb = (org.omg.CORBA.ORB) ctx.lookup("java:comp/ORB");
orb =(org.omg.CORBA.ORB)javax.rmi.PortableRemoteObject.narrow(
ctx.lookup("java:comp/ORB"),
org.omg.CORBA.ORB.class);
运行正常。
2.4 症状:从WAS5.1到WAS6.X 出现的问题,即URL重写导致STRUTS相关的请求均无法正常完成。
解决:主要原因是:getPathInfo,getServletPath的实现有变动,这会影响到struts,acegi等获得路径的行为。
解决方法:
将SWT中的URL重写部分去掉
创建新的RequestProcess,可以只在WAS6.X上才配置用该RequestProcess,在该process中,取得路径后,如果有URL重写部分则将其去掉
配置上新的processor后,工作正常。
附录1:
得到ORB异常信息:
org.omg.CORBA.INTERNAL: vmcid: 0x4f422000 minor code: 77 completed: No
[05-6-21 13:50:59:656 CST] 2dbf5794 SystemErr R at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
[05-6-21 13:50:59:656 CST] 2dbf5794 SystemErr R at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:79)
[05-6-21 13:50:59:656 CST] 2dbf5794 SystemErr R at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java(Compiled Code))
[05-6-21 13:50:59:656 CST] 2dbf5794 SystemErr R at java.lang.reflect.Constructor.newInstance(Constructor.java(Compiled Code))
附录2:
有关InitServlet晚于listener执行的问题,解决无非两种:
1)让Spring在需要时才生成对象
2)自己写listener载入配置(不在InitServlet中进行),且必须在Spring的listener之前执行。
3)规定不要在SPRING管理的类构造函数中调用配置。
目前已按方法2进行。
附录3:
以下是IBM BBS上的一些问答,供参考:
附录:
http://www-128.ibm.com/developerworks/forums/dw_thread.jsp?message=4023650&cat=9&thread=54497&treeDisplayType=threadmode1&forum=266#4023650
JSESSIONID cookie - Help!
Originally posted: 2004 July 15 05:39 AM
Nau Post new reply
Hi, All
I have a need to call a servlet from another one withing the same session:
URL url = new URL( someURL );
URLConnection connection = url.openConnection();
connection.setDoInput( true );
connection.setRequestProperty( "Cookie", "JSESSIONID=" + request.getSession().getId() );
This piece of code works fine for Tomcat but on Webspere I'm getting a new session.
Any help please!
Thanks a million
Re: JSESSIONID cookie - Help!
Originally posted: 2004 July 19 07:15 AM
Ben_ Post new reply
WebSphere generates a cookie named JSESSIONID with value
<your_session>:<websphere_clone_id>.
It can be JSESSIONID=000024N1ZDMZZH022EANUW2ZO5I:u7078j8m, for example.
You can see this if you look at the cookies the browser received or dump the
HTTP request headers.
You built an HTTP request containing the JSESSIONID cookie with
"JSESSIONID=" + request.getSession().getId(), but this code is broken
because getSession().getId() only return the value before the ':' sign in
the cookie value.
Since only the *name* of the cookie is standardized in J2EE (JSESSIONID),
it's a bad idea to assume the format of the cookie is simply the session id,
because the way the *value* of the session cookie is computed is not J2EE
standardized.
You'd better read the actual value from the HTTP request header instead.
Re: JSESSIONID gets overwritten
Originally posted: 2005 Feb 28 05:01 PM
sjostrand2@hotmail.com Post new reply
Lukasz Szelag wrote:
> JSESSIONID gets overwritten in the following scenario:
>
> 1. HTTP Request is sent to "A" URL.
>
> 2. HTTP session is created for "A" and session ID is stored in
> JSESSIONID cookie.
>
> 3. "A" stores an object in the session.
>
> 4. "A" calls "B" ("B" provides a menu)
>
> 5. HTTP session is created for "B" and session ID is stored in
> JSESSIONID cookie overwriting the previous value ("A" session ID).
>
> 6. Second HTTP request is sent to "A" URL.
>
> 7. "A" fails to lookup the object in the session stored in step 3.
> request.getSession(false) returns null.
>
> Is there a way to cure this problem? Thanks.
>
> PS. Not sure if that matters but "A" and "B" are deployed on two
> different servers. Specifying a different names for cookies seems to
> help, i.e. JSESSIONID_A and JSESSIONID_B but this is WebSphere
specific
> extension (Servlet specification requires that the cookie name is
> JSESSIONID).
>
> Lukasz
I assume that A and B are in two different WAR files and therefore have
different context roots, right?
In that case you could use WebSphere's admin console and change the
cookie path from the default (which is /, meaning the cookie is sent as
long as the URL starts with a /, which is always) to the context root
for each application.
So for application A, set the cookie path to /appA_contextRoot and for
application B, set the cookie path to /appB_contextRoot.
In WebSphere's admin console, go to Enterprise Applications ->
Application A -> Session Management -> {click the Enable Cookies link}
and change the Cookie path.
Good luck
/Henrik Sjostrand