< Tomcat 6 >
All implementations of 
Connector support the following attributes:

emptySessionPath

If set to true, all paths for session cookies will be set to /. This can be useful for portlet specification implementations. If not specified, this attribute is set to false.
A side effect to setting this to true, is that if Tomcat creates a new session it will attempt to use the cookie session id if supplied by the client.


All implementations of Context support the following attributes:

crossContext

Set to true if you want calls within this application to ServletContext.getContext() to successfully return a request dispatcher for other web applications running on this virtual host. Set to false (the default) in security conscious environments, to makegetContext() always return null.

sessionCookiePath

The path to be used for all session cookies created for this Context. If not set, the context path will be used. Note that this will be overridden by the emptySessionPath attribute on the connector used to access this Context.



source - http://tomcat.apache.org/tomcat-6.0-doc/config/http.html
source - https://tomcat.apache.org/tomcat-6.0-doc/config/context.html



< Tomcat 7 >
All implementations of Context support the following attributes:

crossContext

Set to true if you want calls within this application to ServletContext.getContext() to successfully return a request dispatcher for other web applications running on this virtual host. Set to false (the default) in security conscious environments, to make getContext() always return null.

 sessionCookiePath

The path to be used for all session cookies created for this context. If set, this overrides any path set by the web application. If not set, the value specified by the web application will be used, or the context path used if the web application does not explicitly set one. To configure all web application to use an empty path (this can be useful for portlet specification implementations) set this attribute to / in the global CATALINA_BASE/conf/context.xml file.

Note: Once one web application using sessionCookiePath="/" obtains a session, all subsequent sessions for any other web application in the same host also configured with sessionCookiePath="/" will always use the same session ID. This holds even if the session is invalidated and a new one created. This makes session fixation protection more difficult and requires custom, Tomcat specific code to change the session ID shared by the multiple applications.


source - http://tomcat.apache.org/tomcat-7.0-doc/config/context.html





[Java Web Application간에 Cross Context에 대한 고찰]

서블릿 웹컨테이너인 Tomcat에 두개의 서블릿(각각 Bar,Foo라고 하죠.)을 올려놓고 Bar, Foo간에 통신하려면 가장 쉽게 생각할 수 있는게 Socket을 연결해주거나 Http로 통신하는 방법이 있을겁니다.


그런데 생각해보면 하나의 컨테이너에 올라온 서블릿이라면 톰켓 설정에 crossContext=true으로 컨텍스트간 참조할 수 있도록 해주면 메모리 내에서 통신이 가능해집니다. 즉, Foo가 Bar의 컨텍스트를 가져와 그곳에 정의된 클래스와 메소드를 리플렉션으로 invoke가 가능하다는 의미입니다. 이때 해당 메소드에 인자를 주면 반환값을 얻어올 수 있죠. 마치 직접 함수를 호출해주는 거죠. 이렇게 하면 Socket 연결비용이나 http 통신비용이 전혀 없지 그저 java객체간 호출정도이기 때문에 성능상 훨씬 이득입니다.


다만, 서블릿간 통신시 각 서블릿내에 정의된 커스텀 클래스로 캐스팅하는 문제가 있습니다. 좀 더 풀어보자면, Foo와 Bar에 동일한 com.cookilab.lib.Person 클래스를 정의했다고 가정하죠. 이건 공용라이브러리로 올린 것도 아니고 Foo, Bar에 각각 static하게 메모리를 먹습니다. 이 경우 Foo가 Bar에 메소드에 Person객체를 인자로 전달하던가 반환으로 받으려 하면 캐스팅문제에 봉착합니다. 왜냐하면 동일한 패키지와 클래스 명이라고 하더라도 각각의 서블릿 메모리상에 올라간 정적 클래스이기 때문에 전혀 다른 클래스인거죠. 그래서 캐스팅이 불가합니다.


http://blog.imaginea.com/cross-context-communication-betwe…/


위 글은 이 문제를 Adaptor를 통해 해결을 보고 있습니다. 여기서 안내하는 방법은 통신비용은 위에서 소개한 대로 동일하게 톰켓의 context공유로 해결하고 다만 데이터 교환은 json으로 합니다. 이때 중간에 adaptor를 둬서 json을 상대 서블릿에 있는 ObjectMapper로 Person객체로 인코딩, 디코딩하는 겁니다.
하지만 기왕에 하는 인메모리 통신인데.... json 인코딩/디코딩이라니요.... ㅡㅡ


이 방법이 아니라 캐스팅 문제를 근본적으로 해결하기 위해서는 결국 서블릿 컨테이너의 공유 라이브러리에 커스텀 클래스(com.jidolstar.myweb.Person)를 올려놓고 Foo와 Bar가 이 클래스를 참고하는 겁니다. 이렇게 하면 클래스 정의가 하나의 메모리를 참조하므로 캐스팅문제가 발생하지 않을겁니다.


뭔가 이렇게 하면 Spring Framework나 각종 라이브러리도 공유해서 쓰면 좋지 않을까 생각됩니다. Foo와 Bar도 가벼워 져서 좋을지도 모르겠다는 생각이 들었습니다.


문제는 Java의 경우 이러한 개발이 여유치 않은 것 같습니다. 많은 책이나 레퍼런스를 보면 공유 라이브러리화 해서 처리하는 것에 대한 기술적 문서가 거의 전무한 것 같습니다. 결국 이것은 이러한 방식으로 하는 것은 Java 서버 프로그램에서는 권장하지 않는 것 같습니다. 하지만 이론적으로는 당연하게도 되거든요. 톰켓은 원래 이걸 지원해줍니다. 당연하게도 자바전체나 톰켓라이브러리전체가 각 서블릿이 컴파일될때 함께 컴파일되는것은 아니지 않겠어요? ^^ 문제는 Spring은 이러한 방식으로 써도 잘 동작할 수 있도록 설계가 되어있는지 전혀 모른다는 점입니다. DI만 생각해도 공유 라이브러리화 해서 제대로 동작할지도 알 수 없습니다.


암튼 Java쪽에 대한 정확한 지식 부족으로 여기까지만 하고 결국 Foo와 Bar는 없는 것으로 하고 하나의 서블릿으로 통합하게 되었습니다. Java 고수님들은 이 부분에 대해서 어떻게 생각하시고 혹시 좋은 해결방법이 있는지 궁금하네요. 개발환경 및 배포환경 전반적으로 의견을 듣고 싶네요.




출처 - https://www.facebook.com/cookilab/posts/918200161570126







Cross-Context Communication between Web Applications 9


The Problem Scenario:

In one of our assignments, we faced a problem in making communication between two different spring based web applications which are in the same web container. Let us explain it with an example; say there are two web applications ‘Foo’ and ‘Bar’ deployed in the same web container and ‘Foo’ depends on ‘Bar’ to access a method say ‘barMethod()’ of ‘BarService’ ( a Java Class present inside the ‘Bar’ application), then

  • The ‘Bar’ application servlet must provide a method to access its Java classes
  • The ‘Foo’ application must get the response from Bar application through HTTP.

Problem#1: Though both the applications reside inside the same container and ‘Foo’ application knows what method of the Java class of ‘Bar’ application it has to access, it has to go through the network using HTTP protocol as if ‘Foo’ application request is considered as a client request to ‘Bar’ application as shown in the figure. Is there an optimal way to avoid the HTTP protocol overhead?



Foo-Bar communication with out Adapter

Problem#2: Say a client (web, mobile etc..) invokes ‘fooMethod()’ of ‘FooService’ which internally calls ‘barMethod()’ of ‘BarService’ through ‘FooServlet’. And say the transaction involved in ‘Foo’ succeeds and the transactions involved in ‘Bar’ fails, then the first transaction gets committed and the second gets rolled-back as the participating threads are different. It means that according to the client, the participating transactions are not atomic as they get partially committed. Is there a way to make them atomic?

The Solution:

Yes..The solution what we found is to use an ‘adapter’ code in a cross-context enabled web container as shown in the figure, which would help in solving both the problems discussed.



Foo-Bar communication With Adapter
  • Enabling cross-context:

Cross-Context is a feature provided by web containers and enabling configuration varies from container to container. For example, in Tomcat, the ‘crossContext’ attribute in ‘Context’ element of ‘TOMCAT_HOME\conf\context.xml’ must be set to true, to enable cross-context communication as shown below. By enabling this, one web application can get access to other web application.

________________________________________________________________

<Context crossContext="true">     
<!-- Default set of monitored resources -->
     
<WatchedResource>
WEB-INF/web.xml</WatchedResource> 
</Context>
________________________________________________________________

  • The Adapter:

Once the ‘Bar’ context is obtainable in ‘Foo’, we can easily get the ‘Bar’ application spring beans using which we can access the ‘barMethod’. Yes!. That’s exactly is what the adapter does. Let us see how to invoke the ‘barMethod’ from ‘Foo’ context in two different sections. The first section explains the adapter functionality if the method invocation involves only simple data types (like int, float, String) as the method arguments/ return type and the second section explains the adapter functionality if the method invocation involves custom data types like (Person, Address etc…).

Handling Simple Data Types

The adapter does the following, before accessing any of the ‘Bar’ application Java classes (‘BarService’),

  • Saves the current class loader (which loaded the ‘Foo’ application) in a temporary variable
  • Sets the current class loader to the one which loaded the ‘Bar’ web application.
  • Resets the current class loader with the one we saved in the temporary variable once it has finished accessing the Java Class of ‘Bar’ application.
  • Let us see the adapter code.

___________________________________________________________________________________________

 String methodName = request.getParameter(WEBConstants.PARAM_METHOD);
 ServletContext srcServletContext = request.getSession().getServletContext();
 ServletContext targetServletContext = srcServletContext.getContext("/Bar");

//save the class loader which loaded the 'Foo' application in a variable
 ClassLoader currentClassLoader = Thread.currentThread().
                                             getContextClassLoader();

 try {
   Object object = targetServletContext.getAttribute
         ("org.springframework.web.servlet.FrameworkServlet.CONTEXT.bar");

// get the class loader which loaded the 'Bar' application
   ClassLoader targetServiceClassLoader = object.getClass().getClassLoader();

// and set it as the current context class loader.
   Thread.currentThread().setContextClassLoader(targetServiceClassLoader);

   Class<?> classBarService = (Class<?>) targetServiceClassLoader.loadClass
                            ("com.pramati.crosscontext.service.BarService");

   Method getBeanMethod = object.getClass().getMethod
                                   ("getBean", String.class);

// Get the barService defined in the 'Bar' application context.
   Object barService = getBeanMethod.invoke(object, "barService");

// Get the method of the 'barService'
   Method targetMethod = classBarService.getMethod(methodName,
                                              (Class[]) null);

   if (targetMethod == null){
        response.getWriter().println(
                "Error: The method['" + methodName + "' does not exist" );
        return null;
   }
// Invoke the method on 'barService'
   Object responseFromBarMethod =
                    targetMethod.invoke(barService, (Object[]) null);
  } catch (Exception e) {
        e.printStackTrace();
  } finally {
        Thread.currentThread().setContextClassLoader(currentClassLoader);
  }

_______________________________________________________________________

If we do not have these steps done, then we end up in getting ‘ClassCastException’ though we cast the right object with right type. Why? It is simple, the class loaders which loaded the ‘Foo’ application and ‘Bar’ application are different.

Handling Custom Data Types

Are there any changes if we need to pass custom type (Person/ Address etc..) parameters while invoking the method on the other context?. Absolutely Yes; we have changes to be made. There are two ways to fix this scenario.

Solution-1: If we could externalize the custom data type classes which are accessed by multiple web applications (here accessed by ‘Foo’ and ‘Bar’) to a different library and place it inside the commons library location of the web container (In case of tomcat, it is <TOMCAT_HOME>\lib), then we can pass the parameters as we did for simple data types without any source code modification.

Solution-2: If we can not externalize the common custom types then the custom data type objects which are going to be used as parameters must be serialized and deserialized say using JSON JavaScript Object Notation (or XML etc..). By including the below snippet to the adapter, we can do it.

___________________________________________________________________________________________

 Person person = new Person(1, "Kayal");
 ObjectMapper jacksonMapper = new ObjectMapper();

// serialize the param 'Person' with the 'Foo' application jacksonMapper
 String serializedPerson = jacksonMapper.writeValueAsString(person);

 Class<?> classPerson = (Class<?>) targetServiceClassLoader.loadClass
                                ("com.pramati.crosscontext.model.Person");

// Get the jacksonMapper defined in the 'Bar' application context.
 Object targetJacksonMapper = getBeanMethod.invoke(object, "jacksonMapper");

//Get the 'readValue' method of the 'Bar' application's jacksonMapper
 Method readValueMethod = targetJacksonMapper.getClass().getMethod
                             ("readValue", String.class, Class.class);

//Deserialize Person using 'readValue()' of the 'Bar' application's jacksonMapper
 Object deserializedPerson = readValueMethod.invoke(targetJacksonMapper,
                               serializedPerson, classPerson);

// invoke 'barMethodWithParam' of 'BarService' with the deserialized Person
 responseFromBarMethod = targetMethod.invoke(barService,  new Object[]
                                            { deserializedPerson});

// Get the 'writeValueAsString' method of the 'Bar' application's jacksonMapper
 Method writeValueAsStringMethod = targetJacksonMapper.getClass().
                               getMethod("writeValueAsString", Object.class);

//serialize response using 'writeValueAsString' of 'Bar' appln's jacksonMapper
 responseFromBarMethod = (String) writeValueAsStringMethod.invoke
                               (targetJacksonMapper, responseFromBarMethod);
___________________________________________________________________________________________

With this,

  • Able to improve performance by avoiding the HTTP protocol overhead.
  • Able to achieve atomicity in transactions.

How? The transactions are cached by the Spring Tx. Manager using ‘Thread Local’ concept which are specific to threads. If we have communication between applications using the adapter, the threads and the participating transactions are same; hence is atomic.




출처 - http://blog.imaginea.com/cross-context-communication-between-web-applications/








tomcat7 context 간 세션 공유 질문 드립니다. (스프링 시큐리티)


안녕하세요. 스타입니다.

스프링 시큐리티 세션 공유에 대한 해결이 되지 않아 많은 자료를 찾아 보다가 답을 찾을 수 없어서 질문 드립니다.

2개의 웹프로젝트이고, web.xml을 각각 가지고 있고
1개의 서버이고, 도메인은 같고 컨텍스트 루트는 각각 /xxx, /yyy 입니다.

세션 공유를 하기 위해 톰캣의 context.xml에 crossContext="true" 옵션을 붙이기도 시도 해 보았는데, 공유가 되지 않았고,

web.xml에 JSESSIONID를 같게 설정 해보았으나, 
/xxx/ 에서 로그인을 성공하고, /yyy/ 경로로 이동하면
로그인 된 것마저 로그아웃 되어 버리네요.

<session-config>
<cookie-config>
<path>/</path>
</cookie-config>
</session-config>


만일 톰캣 클러스터링을 사용한다고 하면, 
같은 주소를 가지고 있는데 어떻게 할 수 있을까요?

도움을 요청 드립니다. 지금 새벽 3시 ㅜ.ㅜ

tomcat 6 이라면 Connector 의 emptySessionPath 속성
http://tomcat.apache.org/tomcat-6.0-doc/config/http.html 

tomcat7 이면 context 의 sessionCookiePath 속성
http://tomcat.apache.org/tomcat-7.0-doc/config/context.html 

쪽을 확인해 보세요





출처 - http://w.okjsp.pe.kr:8080/article/271281








톰캣 context 간의 세션 공유 문제


안녕하세요.
검색을 해도 개념이 잡히지 않아 도움을 청하게 ?습니다...

서버가 단 1대이고 apache 2.2.3 + tomcat 6을 사용해 서비스되고 있습니다.

tomcat 1대에 내에

<Host name="www.test.com">
<Context docBase="/data/test" path="" processTlds="false" reloadable="false" />
<Context docBase="/data/test1" path="/test1" processTlds="false" reloadable="false" />
</Host>

<Host name="m.test.com">
<Context docBase="/data/mtest" path="" processTlds="false" reloadable="false" />
<Context docBase="/data/mtest1" path="/mtest1" processTlds="false" reloadable="false" />
</Host>

이런식으로 host가 2개 등록되어 있고 
각 host 별로 context가 2개 씩 등록되어 있을 경우

01 각 host 내 context 간의 세션 공유
02 host와 host 간의 context 간의 세션 공유

세션을 공유하게 하려면 어떤 방법을 써야 하는지 여?고 싶습니다..(__)

세션 클러스터링의 개념이 정확히 잡히질 않아서
context간의 세션 공유인지 아니면 was가 여러대일 경우의 was간의 공유를 말하는 건지...
또 was 여러대라면 각 was 별로 위와 같이 host 내 context가 다중 일 경우 세션 공유가 어떻게 되는지..

좀 더 검색해 보고 스스로 답을 찾아야 하는데 
질문하는게 참 죄송스럽습니다.

1번은 설정파일에서
crossContext="true"
emptySessionPath="true"
로 해결하시면됩니다.




출처 - http://okky.kr/article/257887









tomcat6 기준이다.

tomcat7에서는 TEST를 해 보지 못했다.




context 구조는 

webapps/project_a

             /project_b



1. 환경 설정

1.context.xml

<Context crossContext="true">

    <Manager pathname="" />

</Context>


2.server.xml

<Connector port="8080" protocol="HTTP/1.1" emptySessionPath="true" connectionTimeout="20000"                 redirectPort="8443" />

2. session 저장 및 호출하기
1. project_a의 session에 저장
session.getServletContext().setAttribute(session.getId(),"박재혁");

2. project_b에서 project_a의 session에 저장한 값 불러오기
HttpSession session = request.getSession();
ServletContext ctx = request.getSession(false).getServletContext().getContext("/project_a");
String name = (String) ctx2.getAttribute(session.getId());



출처 - http://www.jhpark.or.kr/316







하나의 톰캣에 Context가 여러개 추가된 경우에 세션관련 궁금한 점


안녕하세요,, 톰캣 설정을 하다가 궁금한 점이 있어서 질문 올립니다.

하나의 톰캣에 context가 2개 이상 있는 경우에 
context 사이에는 서로 세션공유가 안된다고 되어있습니다.

좀 엉뚱하지만 여기서 궁금한 점이 있어서요..

브라우져와 서버사이의 http통신시 세션 유지는 jsessionid 쿠키값으로 연결되어 있다고 알고 있습니다.  또 쿠키값은 도메인에 따라 관리되는 것으로 알고 있는데요..

그렇다면 하나의 톰캣에 다음의 두 컨텍스트가 있을때http://is.question.kk/ProjectA

도메인이 is.question.kk 으로 같으므로 쿠키가 공유되지 않나요?
쿠키값은 도메인별이지 컨텍스트별로 공유되는게 아니니까..??(맞죠??--;;)
그렇다면 jsessionId는 어떻게 다른 두 컨텍스트에서 별도로 관리되는건지 궁금합니다.

쿠키와 세션 ... 서버..컨텍스트..통합적으로 생각되지 않네요..
아시는 분 답변 부탁드립니다.

감사합니다.


감사합니다. 
쿠키가 url 패스에 따라 생성될수가 있네요.
아마 톰캣에서 jsessionId를 생성할때 context path에 따라 생성하나봐요?ㅎ


출처 - http://okky.kr/article/218240



I have been looking at solutions for sharing session data between mutliple war files. I came across the following solution http://www.fwd.at/tomcat/sharing-session-data-howto.html

The basic idea of it is that if you have more than one war file, you can set a cookie using the sessionid of the first context that is used.

The cookie can be set using a path that will apply to all contexts/applications.

For example, if i have the following configuration for 3 applicatons

/myapp/app1
/myapp/app2
/myapp/app3

I can set a cookie as follows

/myapp sessionid.

The sessionid cookie will then be sent to any request with /myapp in the address. This allows the session id to then be used by any of the contexts.

The only problem with this approach is that it was written in 2003 and tested on Tomcat 4.

What are your opinions of this approach? Is there a better way of doing it?

Thanks


That article is indeed heavily outdated.

On Tomcat 5.5 and 6.0 you can just set emptySessionPath attribute to true in the <Connector>element in /conf/server.xml.

<Connector ... emptySessionPath="true">

On Tomcat 7.0 this has changed because this is now configureable from the Servlet 3.0 API on. It's then on Tomcat's side configureable by setting sessionCookiePath to / in <Context> element in any responsible context.xml file.

<Context ... sessionCookiePath="/">

As said, there's a new Servlet 3.0 API which allows you to configure the session cookie through the standard API. You can do it either declaratively by adding the following to the web.xml:

<session-config>
    <cookie-config>
        <path>/</path>
    </cookie-config>
</session-config>

or programmatically by SessionCookieConfig which is available by ServletContext#getSessionCookieConfig().

getServletContext().getSessionCookieConfig().setPath("/");

You could do this in ServletContextListener#contextInitialized() or HttpServlet#init().

See also:


source - http://stackoverflow.com/questions/9436736/sharing-session-data-between-contexts-in-tomcat






안녕하세요..

JSP로 웹개발중인 초보 jsper 입니다..^^;;

 

다름이 아니오라 5일째 해결책을 찾아 보다 여기까지 오게 되었습니다..

너무너무 궁금하고 해결도 안되고해서 실례하지만 여쭤봐도 될런지요..

구현 방법은 보통 입문 책에서 소개되는 세션 방법입니다.

Struts나 Spring으로 구현한건 아닙니다.

 

현재 폴더가 두개로 나눠 있습니다

 

폴더1

Login/login.jsp, Login/list.jsp

 

폴더2

Board/list.jsp

 

이렇게 다른 폴더에 두개로 나뉘어 있습니다.

 

설명을 드리자면..

Login/login.jsp 에서 세션을 session.setAttribute("MEMBERID", mid); 이렇게 생성을 했습니다.

Login/list.jsp 에서 세션을 String memberid_session =  (String)session.getAttribute("MEMBERID"); 로 받았습니다.

여기까지는 별 문제없이 세션을 주고 받았습니다.

 

그런데

Board/list.jsp 에서 세션을 String memberid_session =  (String)session.getAttribute("MEMBERID"); 으로 받았을때

null로 받아지게 됩니다.

 

제 개발컴에서는 문제없이 값이 받아지는데 운영서버로 업로드해서 부르면 null로 나옵니다.

찾다보니 별의별 방법이 다 있었는데 어떤걸 해봐도 null로 나옵니다.

그래서, 마지막으로 찾은 방법이 톰캣 server.xml에 먼가를 추가하는 부분이 있더라구요..

 

아래 방법은 찾아본 방법입니다.

<Context path="/Login" docBase="C:/tomcat/webapps/Login" debug="0" reloadable="true" crossContext="true"/>

<Context path="/Board" docBase="C:/tomcat/webapps/Board" debug="0" reloadable="true" crossContext="true"/>

 

위와 같이 crossContext로 두 폴더간의 request를 주고 받을 수 있다고 합니다.

 

운영서버라 적용시켜보기전에 함 여쭤 보고 싶어서 질문을 드립니다..

바쁘시더라도 조금만 시간을 내주셔서 가르침을 주시면 감사하겠습니다.


덧글 2개 | 태그 4개 | 관련글보기
 GoodBug
 (0)  (0)

crossContext를 적용하기 전에 몇가지만 확인해 보세요

 

첫번째로..

도메인이 www.domain.com 이고 이서버의 아이피가 100.20.20.2 이렇다면..

www.domain.com/Login/login.jsp 에서 맺은 세션은 100.20.20.2/Login/list.jsp 에서 인식하지 못합니다

즉 세션을 맺은 요청 url 끼리만 세션이 통합니다

login.jsp에서 세션을 맺은 후 Board/list.jsp 로의 이동이 어떻게 되느냐에 따라 세션이 사라질 수도 있습니다

서브도메인도 마찬가지고요..

 

두번째로..

프로그램 로직을 다시 한번 체크해 보세요

세션을 맺은 후 Board/list.jsp로 갈 때 혹시 세션을 삭제하는 로직이 포함되어 있는지(include등) 말입니다

 

제가 볼때는 crossContext는 최후의 방법이구요..

아마 이것을 사용한다 하더라도 안될 가능성이 더 많은것 같네요

 

나중에 해결되시면 꼭 알려 주세요 ^^;

 

   211.189.124.***2008-03-19 12:55:13
 곱슬대마왕
 (0)  (0)

톰캣에 Host name 설정을 하라고 부탁했더니 이걸 IP로 해 놨네요..ㅎ
전 Domainname으로 들어갔구요..

그래서, 그런 오류가 발생했었습니다.. 감사합니다..

주신 답변으로 해결을 한것 같습니다..

감사합니다..^^

   222.237.189.***2008-03-19 15:35:58

Posted by linuxism