Whiteship's Note

유겐 휄러(Juergen Hoeller) 횽아한테 스프링 한 수 배우다.

모하니?/그냥 놀아 : 2008. 5. 17. 09:08

updated 2008-05-17 유겐의 마무리 멘트와 3.0에 추가될 기능 언급 추가. 캬캬캬 끝까지 친절한 유겐 횽.

스프링 지라에 올린 이슈(개선 사항으로..)

We are using GenericController with Spring 2.5 @Controller APIs. And we are using @SessionAttribute like this.
This session attribute name "model" are used by many diffent controllers and many JSPs.

The problem is that diffent session attribute stored with same name(here is "model").
ex, When open pop-up page from parent page, the pop-up page's session attribute will override the parent page's session attribute with same name "model". So, after close the pop-up and if we click save button on parent page, we can meet ClassCastException. ^^;;

We resolve this by modify org.springframework.web.bind.annotation.support.HandlerMethodInvoker class

updateModelAttributes method's

this.sessionAttributeStore.storeAttribute(webRequest, attrName, attrValue);

this.sessionAttributeStore.storeAttribute(webRequest, attrValue.getClass().getSimpleName() + attrName, attrValue);

and resolveModelAttribute method's

Object sessionAttr = this.sessionAttributeStore.retrieveAttribute(webRequest, attrName);

Object sessionAttr = this.sessionAttributeStore.retrieveAttribute(webRequest, paramType.getSimpleName() + attrName);

This modification don't need any change or modification existing Controllers and JSPs. They now use there own session with same name.

How about apply this modification?
And could you remove final keywords from HandlerMethodInvoker to extend that class?

Now we just copy and paste original source and modify this above code, and AnnotationMethodHandlerAdapter too. AnnotationMethodHandlerAdapter class using inner class thar extends HandlerMethodInvoker(ServletHandlerMethodInvoker). So we change the HandlerMethodInvoker import statement in AnnotationMethodHandlerAdapter to our modified version. kk.. Please think about it.

유겐 횽아 1차 답변 및 대안

We actually envisioned such use cases and designed the SessionAttributeStore strategy accordingly... You should be able to implement your custom attribute prefix strategy through decorating the SessionAttributeStore, configuring your custom decorator through the "sessionAttributeStore" property on AnnotationMethodHandlerAdapter.


2차 질문

I saw SessionAttributeStore class but in this case that class cann't help us.

Bacause, the session attribute's (internal) name sould be change according to the command object's class's name(or each controllers).
Yes, we could do this by add @SessionAttribute(name="foobar") on every controllers. but, we made and use custom tags that expects only one session attribute name "model". So we set @SessionAttribute(name="model") this on GenericController and we don't set any @SessinoAttribute on sub-clsss of GenericController.(If you want to see this class code, I can show you.)

With SessionAttributeStrore extending, we can only set a static prefix(this is not what i want.). Even if we can modify storing name by overriding storeAttribute(WebRequest request, String attributeName, Object attributeValue) method with attribute.getClass().getSimpleName()(ex. "Foomodel"), but how can we pick up that session object by that name(ex. "Foomodel") by overring retrieveAttribute(WebRequest request, String attributeName) method. We can't. There is not enough information about runtime command object type or name.

We want to use only one static session attribute name (not prefix) that can be stored and can be retrived according to there runtime object type.(ex. FooController(extends GenericController) reference Foo command object in session by "model"(internally "Foomodel"). And BarController(extends GenericController) also can reference Bar command object in session by "model"(internally "Barmodel".)

So we just do that in here(above modified HandlerMethodInvoker class).
At least we want to extend HandlerMethodInvoker class and set to AnnotationMethodHandlerAdapter.

Is there another way to do this?

유겐 횽아 2차 답변 및 질문 그리고 대안

Good point - you can't include the param type name in the session attribute name that way.

However, I would argue that including the param type is a half-baked solution to begin with: That way you'll isolate per param type, which will work when different windows operate on model attributes of different type. However, what if multiple windows operate on the same type of attribute? What if the same controller gets opened multiple times, e.g. to concurrently edit business accounts of different customers in multiple windows?

The idea behing the SessionAttributeStore strategy is that it may use a custom conversation mechanism: either storing attributes in a managed conversation object instead of in the plain session, or prefixing attribute names with a conversation identifier and still storing them in the session directly. The latter is what I would recommend for your purposes: Determine a conversation identifier for each request (from the given WebRequest object, e.g. from the URL or from a parameter) and use it as a prefix for each attribute name. This will work for storage as well as for retrieval, and will even work for multiple windows that operate on the same type of attribute.


감사의 말

Thanks. I missed that situation (multiple windows on same type) and misunderstanded SessionAttributeStore.
I'll try to use SessionAttributeStore. I really appreciate your recommendation. ^^

문제 해결 알려주기.

Good!! We resolve this issue with you advice.

We made an interceptor that can capture URI, and made a custom SesstionAttributeStore that make session attribute session attribute using captured URI by WebRequest. Finally we configure it to AnnotationMethodHandlerAdapter

We are so impressed to Spring Framework's extensibility and your kind advice. Thanks a lot : )

유겐 횽아 마무리 멘트

Juergen Hoeller resolved SPR-4818.

      Resolution: Won't Fix
   Fix Version/s:     (was: 2.5.5)

OK, good to hear that it works for you! I'm closing this issue then, since the existing SessionAttributeStore strategy seems to be capable of handling this use case.

In Spring 3.0, we intend to provide general conversation support out of the box, also isolating concurrently active browser windows per conversation. This will essentially be a more extensive variant of what you're achieving through your custom SessionAttributeStore - then to be available out of the box in the context of general conversation management.


ps : 유겐 횽아 최고!!
참조: http://jira.springframework.org/browse/SPR-4818

Write a comment.

: 1 : ··· : 65 : 66 : 67 : 68 : 69 : 70 : 71 : 72 : 73 : ··· : 164 :