1 4 package com.tctest.spring.integrationtests.tests; 5 6 import org.apache.commons.httpclient.HostConfiguration; 7 import org.apache.commons.httpclient.HttpClient; 8 import org.apache.commons.httpclient.HttpException; 9 import org.apache.commons.httpclient.HttpMethod; 10 import org.apache.commons.httpclient.HttpState; 11 import org.springframework.beans.factory.BeanFactory; 12 import org.springframework.beans.factory.BeanFactoryAware; 13 import org.springframework.beans.factory.ObjectFactory; 14 import org.springframework.beans.factory.config.Scope; 15 import org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter; 16 import org.springframework.web.context.request.HttpRequestAccessor; 17 import org.springframework.web.context.request.RequestAttributes; 18 import org.springframework.web.context.request.RequestContextHolder; 19 import org.springframework.web.context.request.ServletRequestAttributes; 20 import org.springframework.web.context.request.SessionScope; 21 import org.springframework.web.servlet.DispatcherServlet; 22 23 import com.tc.test.TestConfigObject; 24 import com.tcspring.ComplexBeanId; 25 import com.tcspring.DistributableBeanFactory; 26 import com.tctest.spring.bean.ISimpleBean; 27 import com.tctest.spring.integrationtests.framework.AbstractTwoServerDeploymentTest; 28 import com.tctest.spring.integrationtests.framework.DeploymentBuilder; 29 import com.tctest.spring.integrationtests.framework.ProxyBuilder; 30 31 import java.io.IOException ; 32 import java.util.Collections ; 33 import java.util.HashMap ; 34 import java.util.Iterator ; 35 import java.util.Map ; 36 37 import javax.servlet.http.HttpSessionBindingListener ; 38 39 import junit.framework.Test; 40 41 42 46 public class CustomScopedBeanTest extends AbstractTwoServerDeploymentTest { 47 48 private static final String FASADE_NAME = "TestFasadeService"; 49 50 private static ITestFacade beanN1C1; private static ITestFacade beanN1C2; 53 private static ITestFacade beanN2C1; private static ITestFacade beanN2C2; 56 57 public CustomScopedBeanTest() { 58 this.disableVariant(TestConfigObject.SPRING_VARIANT, "128"); 59 } 60 61 public void testSharedFields() throws Exception { 62 beanN1C1.setField("newVal1"); 63 beanN2C2.setField("newVal2"); 64 65 assertEquals("Failed to share", "newVal1", beanN2C1.getField()); 66 assertEquals("Failed to share", "newVal2", beanN1C2.getField()); 67 } 68 69 public void testScopeId() throws Exception { 70 String id11 = beanN1C1.getConversationId(); 71 String id12 = beanN1C2.getConversationId(); 72 73 String id21 = beanN2C1.getConversationId(); 74 String id22 = beanN2C2.getConversationId(); 75 76 assertEquals("Unexpected scope", id11, id21); 77 assertEquals("Unexpected scope", id12, id22); 78 } 79 80 public void testDestructionCallbacks() throws Exception { 81 String conversationId11 = beanN1C1.getConversationId(); 82 String conversationId21 = beanN1C2.getConversationId(); 83 String conversationId12 = beanN2C1.getConversationId(); 84 String conversationId22 = beanN2C2.getConversationId(); 85 86 beanN1C1.setField("newVal11"); 87 beanN1C2.setField("newVal12"); 88 beanN2C1.setField("newVal21"); 89 beanN2C2.setField("newVal22"); 90 91 assertTrue("Failed to create scoped bean", beanN1C1.isInClusteredSingletonCache(conversationId11)); 92 assertTrue("Failed to create scoped bean", beanN1C2.isInClusteredSingletonCache(conversationId12)); 93 assertTrue("Failed to create scoped bean", beanN2C1.isInClusteredSingletonCache(conversationId21)); 94 assertTrue("Failed to create scoped bean", beanN2C2.isInClusteredSingletonCache(conversationId22)); 95 96 beanN1C1.invokeDestructionCallback(); 97 beanN2C2.invokeDestructionCallback(); 98 99 assertFalse("Failed to destruct scoped bean", beanN1C1.isInClusteredSingletonCache(conversationId11)); 100 assertFalse("Failed to destruct scoped bean", beanN1C2.isInClusteredSingletonCache(conversationId12)); 101 assertFalse("Failed to destruct scoped bean", beanN2C1.isInClusteredSingletonCache(conversationId21)); 102 assertFalse("Failed to destruct scoped bean", beanN2C2.isInClusteredSingletonCache(conversationId22)); 103 } 104 105 public void testTransparentFields() throws Exception { 106 assertEquals("Failed to initialize transient field", "transient-val", beanN1C1.getTransientField()); 107 assertEquals("Failed to initialize transient field", "transient-val", beanN1C2.getTransientField()); 108 assertEquals("Failed to initialize transient field", "transient-val", beanN2C1.getTransientField()); 109 assertEquals("Failed to initialize transient field", "transient-val", beanN2C2.getTransientField()); 110 111 beanN1C1.setTransientField("newVal11"); 112 beanN1C2.setTransientField("newVal12"); 113 beanN2C1.setTransientField("newVal21"); 114 beanN2C2.setTransientField("newVal22"); 115 116 assertEquals("Unexpected sharing", "newVal11", beanN1C1.getTransientField()); 117 assertEquals("Unexpected sharing", "newVal12", beanN1C2.getTransientField()); 118 assertEquals("Unexpected sharing", "newVal21", beanN2C1.getTransientField()); 119 assertEquals("Unexpected sharing", "newVal22", beanN2C2.getTransientField()); 120 } 121 122 123 private static class InnerTestSetup extends TwoSvrSetup { 124 private static final String APP_NAME = "test-customscope"; 125 126 private InnerTestSetup() { 127 super(CustomScopedBeanTest.class, "/tc-config-files/customscoped-tc-config.xml", APP_NAME); 128 } 129 130 protected void setUp() throws Exception { 131 try { 132 super.setUp(); 133 134 Map initCtx = new HashMap (); 135 initCtx.put(ProxyBuilder.EXPORTER_TYPE_KEY, HttpInvokerServiceExporter.class); 136 137 HttpClient clientS1C1 = new HttpClientWithParams(Collections.singletonMap(ConversationScope.CONV_KEY, "(1)")); 138 initCtx.put(ProxyBuilder.HTTP_CLIENT_KEY, clientS1C1); 139 140 beanN1C1 = (ITestFacade) server1.getProxy(ITestFacade.class, APP_NAME + "/http/" + FASADE_NAME, initCtx); 141 beanN2C1 = (ITestFacade) server2.getProxy(ITestFacade.class, APP_NAME + "/http/" + FASADE_NAME, initCtx); 142 143 HttpClient clientS1C2 = new HttpClientWithParams(Collections.singletonMap(ConversationScope.CONV_KEY, "(2)")); 144 clientS1C2.setState(clientS1C1.getState()); initCtx.put(ProxyBuilder.HTTP_CLIENT_KEY, clientS1C2); 146 147 beanN1C2 = (ITestFacade) server1.getProxy(ITestFacade.class, APP_NAME + "/http/" + FASADE_NAME, initCtx); 148 beanN2C2 = (ITestFacade) server2.getProxy(ITestFacade.class, APP_NAME + "/http/" + FASADE_NAME, initCtx); 149 } catch (Exception e) { 150 e.printStackTrace(); 151 throw e; 152 } 153 } 154 155 protected void configureWar(DeploymentBuilder builder) { 156 builder.addBeanDefinitionFile("classpath:/com/tctest/spring/beanfactory-customscope.xml"); 157 158 builder.addRemoteService(HttpInvokerServiceExporter.class, FASADE_NAME, "testFacade", ITestFacade.class); 159 160 builder.setDispatcherServlet("httpinvoker", "/http/*", DispatcherServlet.class, null, true); 161 builder.addDirectoryOrJARContainingClass(net.sf.cglib.core.Constants.class); 162 } 163 } 164 165 166 public static Test suite() { 167 return new InnerTestSetup(); 168 } 169 170 171 174 public static class ConversationScope extends SessionScope implements Scope { 175 public static final String CONV_KEY = "CONVERSATION"; 176 177 public String getConversationId() { 178 String conversation = getWebConversationName(); 179 return conversation == null ? null : super.getConversationId() + conversation; 180 } 181 182 public Object get(String name, ObjectFactory objectFactory) { 183 return super.get(getWebConversationName() + name, objectFactory); 184 } 185 186 public Object remove(String name) { 187 return super.remove(getWebConversationName() + name); 188 } 189 190 public void registerDestructionCallback(String name, Runnable callback) { 191 super.registerDestructionCallback(getWebConversationName() + name, callback); 192 } 193 194 public Object getDestructionCallback(String name) { 195 return RequestContextHolder.currentRequestAttributes().getAttribute( 196 ServletRequestAttributes.DESTRUCTION_CALLBACK_NAME_PREFIX + getWebConversationName() + name, 197 RequestAttributes.SCOPE_SESSION); 198 } 199 200 private String getWebConversationName() { 201 return HttpRequestAccessor.getRequest( 202 (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getParameter(CONV_KEY); 203 } 204 } 205 206 207 public static class HttpClientWithParams extends HttpClient { 208 private Map stickyParameters = null; 209 210 HttpClientWithParams(Map attributes) { 211 this.stickyParameters = attributes; 212 } 213 214 public int executeMethod(HostConfiguration hostconfig, final HttpMethod httpMethod, final HttpState state) 215 throws IOException , HttpException { 216 httpMethod.setQueryString(appendParams(httpMethod.getQueryString())); 217 return super.executeMethod(hostconfig, httpMethod, state); 218 } 219 220 private String appendParams(String queryStr) { 221 StringBuffer sb = new StringBuffer (queryStr == null ? "" : queryStr); 222 if (stickyParameters != null) { 223 for (Iterator iter = this.stickyParameters.entrySet().iterator(); iter.hasNext();) { 224 if (sb.length() > 0) { 225 sb.append('&'); 226 } 227 Map.Entry entry = (Map.Entry ) iter.next(); 228 sb.append(entry.getKey()).append('=').append(entry.getValue()); 229 } 230 } 231 return sb.toString(); 232 } 233 } 234 235 236 public static interface ITestFacade { 237 public String getConversationId(); 238 public String getTransientField(); 239 public void setTransientField(String string); 240 public String getField(); 241 public void setField(String value); 242 public void invokeDestructionCallback(); 243 public boolean isInClusteredSingletonCache(String conversationId); 244 } 245 246 247 public static class ConversationScopeTestFacade implements ITestFacade, BeanFactoryAware { 248 private BeanFactory factory; 249 private ConversationScope scope; 250 private ISimpleBean bean; 251 private String beanName; 252 253 public void setBeanFactory(BeanFactory factory) { 254 this.factory = factory; 255 } 256 257 public void setScope(ConversationScope scope) { 258 this.scope = scope; 259 } 260 261 public void setBean(ISimpleBean bean) { 262 this.bean = bean; 263 } 264 265 public void setField(String value) { 266 bean.setField(value); 267 } 268 269 public String getField() { 270 return bean.getField(); 271 } 272 273 public String getTransientField() { 274 return bean.getTransientField(); 275 } 276 277 public void setTransientField(String value) { 278 bean.setTransientField(value); 279 } 280 281 public String getConversationId() { 282 return scope.getConversationId(); 283 } 284 285 public void invokeDestructionCallback() { 286 System.err.println("#### ConversationScopeTestFacade.invokeDestructionCallback() " + getBeanName()); 287 HttpSessionBindingListener listener = (HttpSessionBindingListener ) scope.getDestructionCallback(getBeanName()); 288 listener.valueUnbound(null); } 290 291 public boolean isInClusteredSingletonCache(String conversationId) { 292 ComplexBeanId beanId = new ComplexBeanId(conversationId, getBeanName()); 293 boolean res = ((DistributableBeanFactory) factory).getBeanContainer(beanId) != null; 294 System.err.println("#### ConversationScopeTestFacade.isInClusteredSingletonCache() " + beanId + " " + res); 295 return res; 296 } 297 298 private String getBeanName() { 299 if(beanName==null) { 300 beanName = bean.getBeanName(); 301 } 302 return beanName; 303 } 304 305 } 306 307 } 308 | Popular Tags |