├── obm ├── src │ ├── test │ │ ├── resources │ │ │ ├── build.sh~ │ │ │ ├── build-thrift.sh │ │ │ ├── crm.proto │ │ │ ├── Crm.thrift │ │ │ ├── crm.avpr │ │ │ └── log4j.properties │ │ └── java │ │ │ └── org │ │ │ └── springframework │ │ │ ├── remoting │ │ │ ├── jbr │ │ │ │ ├── Crm.java │ │ │ │ ├── CrmImpl.java │ │ │ │ ├── Customer.java │ │ │ │ └── TestJbossRemotingExporter.java │ │ │ ├── messagepack │ │ │ │ ├── CatService.java │ │ │ │ ├── EchoService.java │ │ │ │ ├── AlarmService.java │ │ │ │ ├── Human.java │ │ │ │ ├── Cat.java │ │ │ │ └── DefaultEchoService.java │ │ │ ├── avro │ │ │ │ └── TestServiceExportAndConsumption.java │ │ │ └── thrift │ │ │ │ └── TestThriftExporter.java │ │ │ ├── obm │ │ │ ├── messagepack │ │ │ │ ├── TestMessagePackMarshaller.java │ │ │ │ ├── Cat.java │ │ │ │ └── util │ │ │ │ │ └── ResponseArgumentCapturingRequest.java │ │ │ ├── avro │ │ │ │ ├── TestAvroMarshaller.java │ │ │ │ └── crm │ │ │ │ │ ├── Crm.java │ │ │ │ │ ├── User.java │ │ │ │ │ └── Customer.java │ │ │ ├── protocolbuffers │ │ │ │ └── TestProtocolBuffersMarshaller.java │ │ │ ├── thrift │ │ │ │ ├── TestThriftMarshaller.java │ │ │ │ └── ThriftCrmService.java │ │ │ ├── snappy │ │ │ │ └── TestSnappyMarshaller.java │ │ │ └── BaseMarshallerTest.java │ │ │ ├── http │ │ │ └── converter │ │ │ │ └── obm │ │ │ │ ├── support │ │ │ │ ├── DebuggingResponseExtractor.java │ │ │ │ ├── DebugClientHttpRequestInterceptor.java │ │ │ │ └── BaseMarshallingHttpMessageConverterTest.java │ │ │ │ ├── ProtocolBuffersMessageConverterTest.java │ │ │ │ ├── MessagePackHttpMessageConverterTest.java │ │ │ │ ├── ThriftHttpMessageConverterTest.java │ │ │ │ └── AvroHttpMessageConverterTest.java │ │ │ ├── util │ │ │ ├── http │ │ │ │ ├── JettyContextConfigurationCallback.java │ │ │ │ ├── EndpointTestUtils.java │ │ │ │ └── DispatcherServletJettyConfigurationCallback.java │ │ │ └── jms │ │ │ │ └── JmsIntegrationTestUtils.java │ │ │ └── jms │ │ │ └── support │ │ │ └── converter │ │ │ └── obm │ │ │ └── TestJmsMessageConverter.java │ └── main │ │ └── java │ │ └── org │ │ ├── springframework │ │ ├── obm │ │ │ ├── Unmarshaller.java │ │ │ ├── support │ │ │ │ └── AbstractMarshaller.java │ │ │ ├── Marshaller.java │ │ │ ├── messagepack │ │ │ │ ├── util │ │ │ │ │ ├── TypeUtils.java │ │ │ │ │ ├── MessagePackUtils.java │ │ │ │ │ └── ReflectionUtils.java │ │ │ │ ├── support │ │ │ │ │ └── MessagePackRegistrar.java │ │ │ │ └── MessagePackMarshaller.java │ │ │ ├── protocolbuffers │ │ │ │ └── ProtocolBuffersMarshaller.java │ │ │ ├── avro │ │ │ │ ├── support │ │ │ │ │ ├── EncoderFactoryBuilder.java │ │ │ │ │ └── DecoderFactoryBuilder.java │ │ │ │ └── AvroMarshaller.java │ │ │ ├── thrift │ │ │ │ ├── ThriftMarshaller.java │ │ │ │ └── util │ │ │ │ │ └── ThriftUtil.java │ │ │ └── snappy │ │ │ │ └── SnappyMarshaller.java │ │ ├── remoting │ │ │ ├── avro │ │ │ │ ├── AbstractAvroExporter.java │ │ │ │ ├── servers │ │ │ │ │ ├── ServerCreationCallback.java │ │ │ │ │ ├── NettyServerCreationCallback.java │ │ │ │ │ └── SaslServerCreationCallback.java │ │ │ │ ├── clients │ │ │ │ │ ├── NettyTransceiverCreationCallback.java │ │ │ │ │ ├── SaslTransceiverCreationCallback.java │ │ │ │ │ └── TransceiverCreationCallback.java │ │ │ │ ├── AvroServiceExporter.java │ │ │ │ ├── AvroExporter.java │ │ │ │ └── AvroProxyFactoryBean.java │ │ │ ├── jbr │ │ │ │ ├── JbossSerialization.java │ │ │ │ └── JbossRemotingProxyFactoryBean.java │ │ │ ├── thrift │ │ │ │ ├── AbstractThriftExporter.java │ │ │ │ ├── ThriftExporter.java │ │ │ │ ├── ThriftServiceExporter.java │ │ │ │ └── ThriftProxyFactoryBean.java │ │ │ └── messagepack │ │ │ │ ├── EventLoopFactoryBean.java │ │ │ │ └── MessagePackProxyFactoryBean.java │ │ └── http │ │ │ └── converter │ │ │ └── obm │ │ │ └── MarshallingHttpMessageConverter.java │ │ └── apache │ │ └── avro │ │ └── ipc │ │ └── ResponderRequestHandlerUtils.java └── README.txt ├── .gitignore └── README /obm/src/test/resources/build.sh~: -------------------------------------------------------------------------------- 1 | thrift --gen java:java5 -o ../java/ -------------------------------------------------------------------------------- /obm/src/test/resources/build-thrift.sh: -------------------------------------------------------------------------------- 1 | thrift --gen java:java5 -out ../java/ Crm.thrift -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .classpath 3 | .project 4 | .settings 5 | *.ipr 6 | *.iws 7 | *.iml 8 | target 9 | .dropbox 10 | activemq-data 11 | -------------------------------------------------------------------------------- /obm/src/test/resources/crm.proto: -------------------------------------------------------------------------------- 1 | package crm; 2 | 3 | option java_package = "org.springframework.obm.protocolbuffers.crm"; 4 | option java_outer_classname= "Crm"; 5 | option optimize_for = SPEED; 6 | 7 | message Customer { 8 | optional int64 id =1; 9 | required string firstName = 2; 10 | required string lastName = 3; 11 | required string email= 4; 12 | } 13 | -------------------------------------------------------------------------------- /obm/src/test/resources/Crm.thrift: -------------------------------------------------------------------------------- 1 | namespace java org.springframework.obm.thrift.crm 2 | 3 | /** 4 | * the type of the entity object 5 | */ 6 | struct Customer { 7 | 1:required string firstName; 8 | 2:required string lastName; 9 | 3:string email; 10 | 4:i32 id; 11 | } 12 | 13 | struct User { 14 | 1:required string email; 15 | 2:required string password; 16 | 3:i32 id; 17 | } 18 | 19 | service UserManager { 20 | User login(1:string email, 2:string password); 21 | } 22 | 23 | /** 24 | * the CRM service interface 25 | */ 26 | service Crm { 27 | 28 | Customer createCustomer( 1:string fn, 2:string ln, 3:string email ); 29 | 30 | Customer getCustomerById( 1:i32 customerId); 31 | } -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/remoting/jbr/Crm.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.remoting.jbr; 17 | 18 | public interface Crm { 19 | Customer getCustomerById(long id); 20 | } -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/remoting/messagepack/CatService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.remoting.messagepack; 18 | 19 | /** 20 | * @author Josh Long 21 | */ 22 | public interface CatService { 23 | Cat fetch(); 24 | } 25 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/remoting/jbr/CrmImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.remoting.jbr; 17 | 18 | 19 | public class CrmImpl implements Crm { 20 | public Customer getCustomerById(long id) { 21 | return new Customer(id, "josh", "long"); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/remoting/messagepack/EchoService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.remoting.messagepack; 18 | 19 | /** 20 | * @author Josh Long 21 | */ 22 | public interface EchoService extends AlarmService { 23 | String echo(String in); 24 | 25 | Cat fetch(); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/obm/Unmarshaller.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.obm; 18 | 19 | 20 | import java.io.InputStream; 21 | 22 | public interface Unmarshaller { 23 | 24 | boolean supports(Class clazz); 25 | 26 | T unmarshal(Class clazz, InputStream source) throws Exception; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/obm/messagepack/TestMessagePackMarshaller.java: -------------------------------------------------------------------------------- 1 | package org.springframework.obm.messagepack; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | import org.springframework.obm.BaseMarshallerTest; 6 | 7 | /** 8 | * Test of the {@link MessagePackMarshaller} 9 | * 10 | * @author Josh Long 11 | */ 12 | public class TestMessagePackMarshaller extends BaseMarshallerTest { 13 | 14 | private Cat cat = new Cat(); 15 | 16 | @Before 17 | public void before() throws Throwable { 18 | 19 | cat.setId(4); 20 | cat.setName("Felix"); 21 | 22 | MessagePackMarshaller messagePackMarshaller = new MessagePackMarshaller(); 23 | messagePackMarshaller.afterPropertiesSet(); 24 | 25 | setMarshaller(messagePackMarshaller); 26 | setUnmarshaller(messagePackMarshaller); 27 | } 28 | 29 | @Test 30 | public void testMarshalling() throws Throwable { 31 | doTestMarshalling(Cat.class, this.cat); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/remoting/messagepack/AlarmService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.remoting.messagepack; 18 | 19 | 20 | /** 21 | * interface that requires support for broadcasting (in all-caps, no less!) a given message. 22 | * 23 | * @author Josh Long 24 | */ 25 | public interface AlarmService { 26 | 27 | String alarm(String msg); 28 | } 29 | -------------------------------------------------------------------------------- /obm/src/test/resources/crm.avpr: -------------------------------------------------------------------------------- 1 | { 2 | "namespace" : "org.springframework.obm.avro.crm", 3 | "saslProtocol" : "Crm", 4 | "types" : [ 5 | { 6 | "name" : "Customer", "type": "record", 7 | "fields" : [ 8 | { "name" : "firstName", "type": ["string","null"] }, 9 | { "name" : "lastName", "type": ["string","null"] }, 10 | { "name" : "email", "type": ["string","null"] }, 11 | { "name" : "id", "type": ["int","null"] } 12 | ] 13 | }, 14 | { 15 | "name" : "User", "type": "record", 16 | "fields" : [ 17 | { "name" : "email", "type": ["string","null"] }, 18 | { "name" : "password", "type": ["string","null"] } 19 | ] 20 | } 21 | 22 | ], 23 | "messages" : { 24 | "createCustomer" : { 25 | "request" : [ { "name" : "fn", "type": "string"}, { "name" : "ln", "type": "string"}, { "name" : "email", "type": "string"} ], 26 | "response" : "Customer" 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/obm/avro/TestAvroMarshaller.java: -------------------------------------------------------------------------------- 1 | package org.springframework.obm.avro; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | import org.springframework.obm.BaseMarshallerTest; 6 | import org.springframework.obm.avro.crm.Customer; 7 | 8 | /** 9 | * @author Josh Long 10 | */ 11 | public class TestAvroMarshaller extends BaseMarshallerTest { 12 | private Customer customer = new Customer(); 13 | 14 | @Before 15 | public void before() throws Throwable { 16 | // the public fields-based approach is ... regrettable 17 | // the 1.6 version of Avro will remedy this: AVRO-784 or AVRO-839 18 | customer.id = 225; 19 | customer.firstName = "Josh"; 20 | customer.lastName = "Long"; 21 | customer.email = "josh@emai.com"; 22 | 23 | AvroMarshaller am = new AvroMarshaller(); 24 | setMarshaller(am); 25 | setUnmarshaller(am); 26 | } 27 | 28 | @Test 29 | public void testMarshalling() throws Throwable { 30 | doTestMarshalling(Customer.class, this.customer); 31 | } 32 | } -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/remoting/avro/AbstractAvroExporter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.remoting.avro; 18 | 19 | import org.apache.avro.ipc.Responder; 20 | import org.apache.avro.ipc.specific.SpecificResponder; 21 | import org.springframework.remoting.support.RemoteExporter; 22 | 23 | public class AbstractAvroExporter extends RemoteExporter { 24 | 25 | protected Responder getResponder() { 26 | return new SpecificResponder(getServiceInterface(), getService()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/remoting/avro/servers/ServerCreationCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.remoting.avro.servers; 18 | 19 | import org.apache.avro.ipc.Responder; 20 | import org.apache.avro.ipc.Server; 21 | 22 | import java.net.InetSocketAddress; 23 | 24 | /** 25 | * Callback to allow clients to tailor which server is used. 26 | * 27 | * @author Josh Long 28 | */ 29 | public interface ServerCreationCallback { 30 | Server buildServer(InetSocketAddress address, Responder responder) throws Exception; 31 | } 32 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/http/converter/obm/support/DebuggingResponseExtractor.java: -------------------------------------------------------------------------------- 1 | package org.springframework.http.converter.obm.support; 2 | 3 | import org.apache.commons.logging.Log; 4 | import org.apache.commons.logging.LogFactory; 5 | import org.springframework.http.HttpHeaders; 6 | import org.springframework.http.client.ClientHttpResponse; 7 | import org.springframework.web.client.ResponseExtractor; 8 | 9 | import java.io.IOException; 10 | 11 | public class DebuggingResponseExtractor implements ResponseExtractor { 12 | private Log log = LogFactory.getLog(getClass()); 13 | 14 | @Override 15 | public Object extractData(ClientHttpResponse response) throws IOException { 16 | debug("Response: ", response.getHeaders()); 17 | return null; 18 | } 19 | 20 | private void debug(String title, HttpHeaders headers) { 21 | if (log.isDebugEnabled()) { 22 | log.debug("============== " + title + " =============="); 23 | } 24 | for (String k : headers.keySet()) { 25 | if (log.isDebugEnabled()) { 26 | log.debug(String.format("%s = %s", k, headers.get(k))); 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/obm/avro/crm/Crm.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Autogenerated by Avro 3 | * 4 | * DO NOT EDIT DIRECTLY 5 | */ 6 | package org.springframework.obm.avro.crm; 7 | 8 | @SuppressWarnings("all") 9 | public interface Crm { 10 | public static final org.apache.avro.Protocol PROTOCOL = org.apache.avro.Protocol.parse("{\"protocol\":\"CrmImpl\",\"namespace\":\"org.springframework.obm.avro.crm\",\"types\":[{\"type\":\"record\",\"name\":\"Customer\",\"fields\":[{\"name\":\"firstName\",\"type\":[\"string\",\"null\"]},{\"name\":\"lastName\",\"type\":[\"string\",\"null\"]},{\"name\":\"email\",\"type\":[\"string\",\"null\"]},{\"name\":\"id\",\"type\":[\"int\",\"null\"]}]},{\"type\":\"record\",\"name\":\"User\",\"fields\":[{\"name\":\"email\",\"type\":[\"string\",\"null\"]},{\"name\":\"password\",\"type\":[\"string\",\"null\"]}]}],\"messages\":{\"createCustomer\":{\"request\":[{\"name\":\"fn\",\"type\":\"string\"},{\"name\":\"ln\",\"type\":\"string\"},{\"name\":\"email\",\"type\":\"string\"}],\"response\":\"Customer\"}}}"); 11 | 12 | org.springframework.obm.avro.crm.Customer createCustomer(java.lang.CharSequence fn, java.lang.CharSequence ln, java.lang.CharSequence email) throws org.apache.avro.AvroRemoteException; 13 | } 14 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/remoting/avro/clients/NettyTransceiverCreationCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.remoting.avro.clients; 18 | 19 | import org.apache.avro.ipc.NettyTransceiver; 20 | import org.apache.avro.ipc.Transceiver; 21 | 22 | import java.net.InetSocketAddress; 23 | 24 | public class NettyTransceiverCreationCallback implements TransceiverCreationCallback { 25 | 26 | @Override 27 | public Transceiver buildTransceiver(InetSocketAddress address) throws Exception { 28 | return new NettyTransceiver(address); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/obm/protocolbuffers/TestProtocolBuffersMarshaller.java: -------------------------------------------------------------------------------- 1 | package org.springframework.obm.protocolbuffers; 2 | 3 | 4 | import org.junit.Assert; 5 | import org.junit.Before; 6 | import org.junit.Test; 7 | import org.springframework.obm.BaseMarshallerTest; 8 | import org.springframework.obm.protocolbuffers.crm.Crm; 9 | 10 | /** 11 | * @author Josh Long 12 | */ 13 | public class TestProtocolBuffersMarshaller extends BaseMarshallerTest { 14 | 15 | private Crm.Customer customer; 16 | 17 | @Before 18 | public void before() throws Throwable { 19 | 20 | customer = Crm.Customer.newBuilder() 21 | .setEmail("email@email.com") 22 | .setFirstName("josh") 23 | .setLastName("long").build(); 24 | 25 | Assert.assertNotNull(customer); 26 | 27 | ProtocolBuffersMarshaller protocolBuffersMarshaller = new ProtocolBuffersMarshaller(); 28 | 29 | setMarshaller(protocolBuffersMarshaller); 30 | setUnmarshaller(protocolBuffersMarshaller); 31 | } 32 | 33 | @Test 34 | public void testMarshalling() throws Throwable { 35 | doTestMarshalling(Crm.Customer.class, this.customer); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/obm/support/AbstractMarshaller.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.obm.support; 18 | 19 | import org.apache.commons.logging.Log; 20 | import org.apache.commons.logging.LogFactory; 21 | import org.springframework.obm.Marshaller; 22 | import org.springframework.obm.Unmarshaller; 23 | 24 | /** 25 | * Simple base class to make sure we make as many things common and reusable as possible 26 | * 27 | * @author Josh Long 28 | */ 29 | abstract public class AbstractMarshaller implements Marshaller, Unmarshaller { 30 | 31 | 32 | protected Log log = LogFactory.getLog(getClass()); 33 | 34 | 35 | } 36 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/util/http/JettyContextConfigurationCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.util.http; 18 | 19 | import org.mortbay.jetty.servlet.Context; 20 | 21 | /** 22 | *

hook so that clients may configure a working jetty server's {@link Context}

23 | *

the advantage in exposing this as a separate interface is that we can now 24 | * reuse the common recipes (such as for Spring MVC's {@link org.springframework.web.servlet.DispatcherServlet}) 25 | *

26 | * 27 | * @author Josh Long 28 | */ 29 | public interface JettyContextConfigurationCallback { 30 | void configure(Context c) throws Exception; 31 | } -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/remoting/avro/clients/SaslTransceiverCreationCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.remoting.avro.clients; 17 | 18 | import org.apache.avro.ipc.SaslSocketTransceiver; 19 | import org.apache.avro.ipc.Transceiver; 20 | 21 | import java.net.InetSocketAddress; 22 | 23 | /** 24 | * Implements {@link TransceiverCreationCallback} which in turn 25 | * 26 | * @author Josh Long 27 | */ 28 | public class SaslTransceiverCreationCallback implements TransceiverCreationCallback { 29 | @Override 30 | public Transceiver buildTransceiver(InetSocketAddress address) throws Exception { 31 | return new SaslSocketTransceiver(address); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/remoting/avro/clients/TransceiverCreationCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.remoting.avro.clients; 18 | 19 | 20 | import org.apache.avro.ipc.Transceiver; 21 | 22 | import java.net.InetSocketAddress; 23 | 24 | /** 25 | * Interface so that a client may plugin any implementation 26 | * of the {@link Transceiver} interface while benefiting from the defaults of the 27 | * {@link org.springframework.remoting.avro.AvroProxyFactoryBean} as well as reducing to truly unique concerns the 28 | * configuration required 29 | * 30 | * @author Josh Long 31 | */ 32 | public interface TransceiverCreationCallback { 33 | Transceiver buildTransceiver(InetSocketAddress address) throws Exception; 34 | } 35 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/obm/messagepack/Cat.java: -------------------------------------------------------------------------------- 1 | package org.springframework.obm.messagepack; 2 | 3 | /** 4 | * dummy entity to test 5 | * 6 | * @author Josh Long 7 | */ 8 | public class Cat { 9 | private String name; 10 | 11 | private int id; 12 | 13 | public String getName() { 14 | return name; 15 | } 16 | 17 | public void setName(String name) { 18 | this.name = name; 19 | } 20 | 21 | public int getId() { 22 | return id; 23 | } 24 | 25 | public void setId(int id) { 26 | this.id = id; 27 | } 28 | 29 | public Cat(String name, int id) { 30 | this.name = name; 31 | this.id = id; 32 | } 33 | 34 | public Cat() { 35 | } 36 | 37 | @Override 38 | public boolean equals(Object o) { 39 | if (this == o) { 40 | return true; 41 | } 42 | if (o == null || getClass() != o.getClass()) { 43 | return false; 44 | } 45 | 46 | Cat that = (Cat) o; 47 | 48 | return id == that.id && !(name != null ? !name.equals(that.name) : that.name != null); 49 | 50 | } 51 | 52 | @Override 53 | public String toString() { 54 | return "Cat{" + 55 | "name='" + name + '\'' + 56 | ", id=" + id + 57 | '}'; 58 | } 59 | 60 | @Override 61 | public int hashCode() { 62 | int result = name != null ? name.hashCode() : 0; 63 | result = 31 * result + id; 64 | return result; 65 | } 66 | } -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/remoting/jbr/JbossSerialization.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.remoting.jbr; 17 | 18 | 19 | /** 20 | * Enum for the two types of Java serialization supported by JBoss Remoting 21 | *

22 | *

    23 | *
  • Java RMI serialization, which delegates to RMI
  • 24 | *
  • JBoss Serialization, which is smarter in how it clones objects, avoids the need to implement {@link java.io.Serializable} and to provide a SerialUID
  • 25 | *
26 | * 27 | * @author Josh Long 28 | */ 29 | public enum JbossSerialization { 30 | 31 | /** 32 | * this is basically a fallback to RMI 33 | */ 34 | JAVA, 35 | 36 | /** 37 | * this is the default in both the client and the 38 | * server components provided by this support, and lets you serialize 39 | * virtually any object over the wire. 40 | */ 41 | JBOSS 42 | 43 | } 44 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/remoting/avro/servers/NettyServerCreationCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.remoting.avro.servers; 17 | 18 | import org.apache.avro.ipc.NettyServer; 19 | import org.apache.avro.ipc.Responder; 20 | import org.apache.avro.ipc.Server; 21 | 22 | import java.net.InetSocketAddress; 23 | 24 | /** 25 | *

26 | * implementation of {@link org.springframework.remoting.avro.AvroExporter} that builds a {@link NettyServer}. 27 | *

28 | * This should be your default choice to expose services in the {@link org.springframework.remoting.avro.AvroExporter} tree. 29 | * 30 | * @author Josh Long 31 | */ 32 | public class NettyServerCreationCallback implements ServerCreationCallback { 33 | 34 | @Override 35 | public Server buildServer(InetSocketAddress address, Responder responder) throws Exception { 36 | return new NettyServer(responder, address); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/obm/thrift/TestThriftMarshaller.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.obm.thrift; 17 | 18 | 19 | import org.junit.Before; 20 | import org.junit.Test; 21 | import org.springframework.obm.BaseMarshallerTest; 22 | import org.springframework.obm.thrift.crm.Customer; 23 | 24 | /** 25 | * @author Josh Long 26 | */ 27 | public class TestThriftMarshaller extends BaseMarshallerTest { 28 | 29 | private Customer customer = new Customer("Josh", "Long", "josh@email.com", 242); 30 | 31 | @Before 32 | public void before() throws Throwable { 33 | 34 | ThriftMarshaller marshaller = new ThriftMarshaller(); 35 | marshaller.afterPropertiesSet(); 36 | 37 | setMarshaller(marshaller); 38 | setUnmarshaller(marshaller); 39 | } 40 | 41 | @Test 42 | public void testMarshaller() throws Throwable { 43 | doTestMarshalling(Customer.class, customer); 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/obm/Marshaller.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.obm; 18 | 19 | 20 | import java.io.OutputStream; 21 | 22 | /** 23 | *

24 | * Defines the contract for Object to Binary Marshallers. Implementations of this interface 25 | * can serialize a given Object to an {@link OutputStream}. 26 | *

27 | *

Although the marshal method accepts a java.lang.Object as its 28 | * first parameter, most Marshaller implementations cannot handle arbitrary 29 | * Objects. Instead, a object class must be registered with the thriftMarshaller, 30 | * or have a common base class. 31 | * 32 | * @author Josh Long 33 | * @see org.springframework.obm.Unmarshaller 34 | * @see org.springframework.oxm.Marshaller 35 | * @see org.springframework.oxm.Unmarshaller 36 | */ 37 | public interface Marshaller { 38 | 39 | boolean supports(Class clazz); 40 | 41 | void marshal(T obj, OutputStream os) throws Exception; 42 | 43 | } 44 | -------------------------------------------------------------------------------- /obm/src/main/java/org/apache/avro/ipc/ResponderRequestHandlerUtils.java: -------------------------------------------------------------------------------- 1 | package org.apache.avro.ipc; 2 | 3 | import org.apache.avro.AvroRuntimeException; 4 | import org.springframework.http.MediaType; 5 | 6 | import javax.servlet.ServletException; 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | import java.io.IOException; 10 | import java.nio.ByteBuffer; 11 | import java.util.List; 12 | 13 | /** 14 | * This is required to get insight into the package private static methods on {@link ResponderServlet} which are crucial for 15 | * the server side component of any HTTP based server 16 | *

17 | * Hackety. 18 | * 19 | * @author Josh Long 20 | */ 21 | abstract public class ResponderRequestHandlerUtils { 22 | 23 | /** 24 | * this is only useful to make the various package private methods on {@link HttpTransceiver} visible to other components. 25 | *

26 | * This code is taken almost verbatim from {@link ResponderServlet} 27 | */ 28 | public static void handleRequest(MediaType mediaType, HttpServletRequest request, HttpServletResponse response, Responder responder) throws IOException, ServletException { 29 | response.setContentType(mediaType.toString()); 30 | List requestBufs = HttpTransceiver.readBuffers(request.getInputStream()); 31 | try { 32 | List responseBufs = responder.respond(requestBufs); 33 | response.setContentLength(HttpTransceiver.getLength(responseBufs)); 34 | HttpTransceiver.writeBuffers(responseBufs, response.getOutputStream()); 35 | } catch (AvroRuntimeException e) { 36 | throw new ServletException(e); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/remoting/messagepack/Human.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.remoting.messagepack; 18 | 19 | /** 20 | * @author Josh Long 21 | */ 22 | public class Human { 23 | private String name; 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | 29 | public void setName(String name) { 30 | this.name = name; 31 | } 32 | 33 | public Human() { 34 | } 35 | 36 | @Override 37 | public boolean equals(Object o) { 38 | if (this == o) { 39 | return true; 40 | } 41 | if (o == null || getClass() != o.getClass()) { 42 | return false; 43 | } 44 | 45 | Human human = (Human) o; 46 | 47 | if (name != null ? !name.equals(human.name) : human.name != null) { 48 | return false; 49 | } 50 | 51 | return true; 52 | } 53 | 54 | @Override 55 | public int hashCode() { 56 | return name != null ? name.hashCode() : 0; 57 | } 58 | 59 | public Human(String name) { 60 | this.name = name; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/obm/messagepack/util/ResponseArgumentCapturingRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.obm.messagepack.util; 18 | 19 | 20 | import org.msgpack.MessagePackObject; 21 | import org.msgpack.rpc.Request; 22 | import org.msgpack.rpc.transport.MessageSendable; 23 | 24 | /** 25 | * Shim to get in and see and expose the results of a call that uses a {@link java.util.concurrent.Future} in MessagePack 26 | */ 27 | public class ResponseArgumentCapturingRequest extends Request { 28 | public ResponseArgumentCapturingRequest(MessageSendable channel, int msgid, String method, MessagePackObject args) { 29 | super(channel, msgid, method, args); 30 | } 31 | 32 | public ResponseArgumentCapturingRequest(String method, MessagePackObject args) { 33 | super(method, args); 34 | } 35 | 36 | private Object result; 37 | 38 | @Override 39 | public void sendResult(Object result) { 40 | this.result = result; 41 | super.sendResult(result); 42 | } 43 | 44 | public Object getResult() { 45 | return result; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/obm/avro/crm/User.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Autogenerated by Avro 3 | * 4 | * DO NOT EDIT DIRECTLY 5 | */ 6 | package org.springframework.obm.avro.crm; 7 | 8 | @SuppressWarnings("all") 9 | public class User extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord { 10 | public static final org.apache.avro.Schema SCHEMA$ = org.apache.avro.Schema.parse("{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"org.springframework.obm.avro.crm\",\"fields\":[{\"name\":\"email\",\"type\":[\"string\",\"null\"]},{\"name\":\"password\",\"type\":[\"string\",\"null\"]}]}"); 11 | public java.lang.CharSequence email; 12 | public java.lang.CharSequence password; 13 | 14 | public org.apache.avro.Schema getSchema() { 15 | return SCHEMA$; 16 | } 17 | 18 | // Used by DatumWriter. Applications should not call. 19 | public java.lang.Object get(int field$) { 20 | switch (field$) { 21 | case 0: 22 | return email; 23 | case 1: 24 | return password; 25 | default: 26 | throw new org.apache.avro.AvroRuntimeException("Bad index"); 27 | } 28 | } 29 | 30 | // Used by DatumReader. Applications should not call. 31 | @SuppressWarnings(value = "unchecked") 32 | public void put(int field$, java.lang.Object value$) { 33 | switch (field$) { 34 | case 0: 35 | email = (java.lang.CharSequence) value$; 36 | break; 37 | case 1: 38 | password = (java.lang.CharSequence) value$; 39 | break; 40 | default: 41 | throw new org.apache.avro.AvroRuntimeException("Bad index"); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/http/converter/obm/ProtocolBuffersMessageConverterTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.http.converter.obm; 2 | 3 | import org.apache.commons.logging.Log; 4 | import org.apache.commons.logging.LogFactory; 5 | import org.junit.Before; 6 | import org.junit.Test; 7 | import org.springframework.http.MediaType; 8 | import org.springframework.http.converter.obm.support.BaseMarshallingHttpMessageConverterTest; 9 | import org.springframework.obm.protocolbuffers.ProtocolBuffersMarshaller; 10 | import org.springframework.obm.protocolbuffers.crm.Crm; 11 | 12 | /** 13 | * Simple test of the Google Protocols marshaller with {@link org.springframework.http.converter.HttpMessageConverter} 14 | * 15 | * @author Josh Long 16 | */ 17 | public class ProtocolBuffersMessageConverterTest extends BaseMarshallingHttpMessageConverterTest { 18 | 19 | private Crm.Customer customer; 20 | 21 | private Log log = LogFactory.getLog(getClass()); 22 | 23 | static MediaType MEDIA_TYPE = new MediaType("application", "x-protobuffs"); 24 | 25 | @Before 26 | public void before() throws Throwable { 27 | customer = Crm.Customer.newBuilder() 28 | .setEmail("email@email.com") 29 | .setFirstName("josh") 30 | .setLastName("long").build(); 31 | ProtocolBuffersMarshaller marshaller = new ProtocolBuffersMarshaller(); 32 | 33 | setMarshaller(marshaller); 34 | setUnmarshaller(marshaller); 35 | setMediaType(MEDIA_TYPE); 36 | MarshallingHttpMessageConverter converter = new MarshallingHttpMessageConverter(marshaller); 37 | setHttpMessageConverter(converter); 38 | } 39 | 40 | @Test 41 | public void testHttpReading() throws Throwable { 42 | doTestHttpWriting(customer.getClass(), this.customer); 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/obm/snappy/TestSnappyMarshaller.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.obm.snappy; 18 | 19 | import org.junit.Before; 20 | import org.junit.Test; 21 | import org.springframework.obm.BaseMarshallerTest; 22 | import org.springframework.obm.thrift.ThriftMarshaller; 23 | import org.springframework.obm.thrift.crm.Customer; 24 | 25 | /** 26 | * Snappy is a compression Marshaller that wraps other Marshallers. 27 | * 28 | * @author Josh Long 29 | */ 30 | public class TestSnappyMarshaller extends BaseMarshallerTest { 31 | 32 | private Customer customer = new Customer("Josh", "Long", "josh@email.com", 242); 33 | 34 | @Before 35 | public void before() throws Throwable { 36 | 37 | ThriftMarshaller marshaller = new ThriftMarshaller(); 38 | marshaller.afterPropertiesSet(); 39 | 40 | SnappyMarshaller snappyMarshaller = new SnappyMarshaller(marshaller); 41 | 42 | setMarshaller(snappyMarshaller); 43 | setUnmarshaller(snappyMarshaller); 44 | } 45 | 46 | @Test 47 | public void testMarshaller() throws Throwable { 48 | doTestMarshalling(Customer.class, customer); 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | the spring framework has long supported a consistant raft of RPC mechanisms 2 | with its Service Exporters. As of Spring 3.0, it's also provided a nice SPI 3 | to support arbitrary serializers (marshallers, or, more properly, 4 | HttpMessageConverters) in the REST support provided by the framework. 5 | 6 | Both of these mechanisms are powerful, and expose flexible SPIs that can be 7 | used to teach Spring new tricks. 8 | 9 | This is particularly valuable in the world of serializers and RPC 10 | mechanisms, which tend to move much quicker than individual Spring framework 11 | releases. For example, Cassandra (itself only a 0.7 project!) has already 12 | had a full integration with Thrift and has now moved on to support Avro. 13 | Ex-Googler Dhanji Prasana called (http://rethrick.com/#waving-goodbye) Google's 14 | Protocol Buffers (which Google's used over a few iterations for years) an 15 | "ancient, creaking dinosaurs" compared to MessagePack, JSON, and Hadoop. 16 | 17 | So, understanding that the space is too voilatile to try to track in Spring 18 | proper, I've started building these implementations. 19 | 20 | todo: 21 | the support defined here should work for: 22 | -- service exporters (where possible) 23 | -- HttpMessageConverters (REST serialization) 24 | -- JMS MessageConverters 25 | -- AMQP MessageConverters 26 | 27 | serialization technologies to support include: 28 | -- Avro 29 | -- Thrift 30 | -- MessagePack 31 | -- Google Protocol Buffers 32 | 33 | RPC technologies include 34 | -- JBoss Remoting 35 | -- MessagePack RPC 36 | -- Thrift RPC 37 | -- Avro 38 | -- Netty? 39 | 40 | Approach 41 | New Note 5 42 | 43 | Build Spring OBM -- object-to-binary marshallers. this would let you then 44 | build ONE JMS MessageConverter and ONE AMQP MessageConverter and ONE 45 | HttpMessageConverter and then delegate to the object-to-binary marshaller 46 | and unmarshaller, a la Spring OXM 47 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/remoting/jbr/Customer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.remoting.jbr; 17 | 18 | 19 | public class Customer { 20 | 21 | private long id; 22 | 23 | private String firstName, lastName; 24 | 25 | public Customer(long id, String firstName, String lastName) { 26 | this.id = id; 27 | this.firstName = firstName; 28 | this.lastName = lastName; 29 | } 30 | 31 | @Override 32 | public String toString() { 33 | return "Customer{" + 34 | "firstName='" + firstName + '\'' + 35 | ", lastName='" + lastName + '\'' + 36 | ", id=" + id + 37 | '}'; 38 | } 39 | 40 | public String getFirstName() { 41 | return firstName; 42 | } 43 | 44 | public void setFirstName(String firstName) { 45 | this.firstName = firstName; 46 | } 47 | 48 | public String getLastName() { 49 | return lastName; 50 | } 51 | 52 | public void setLastName(String lastName) { 53 | this.lastName = lastName; 54 | } 55 | 56 | public long getId() { 57 | return id; 58 | } 59 | 60 | public void setId(long id) { 61 | this.id = id; 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /obm/README.txt: -------------------------------------------------------------------------------- 1 | Notes on other things to potentially support: 2 | -- google snappy compression support 3 | -- jboss remoting endpoint 4 | -- edmunds' particular version of thrift? 5 | 6 | If you're new to Thrift, then you might check the apache website to see if they've yet finished that tutorial (doubt it.) 7 | 8 | Here's one that's quite good: http://www.thrift.pl/Thrift-tutorial-installation.html 9 | Also, see http://blog.newitfarmer.com/software-develop/open-source/869/install-thrift-on-linux/ 10 | Also, http://diwakergupta.github.com/thrift-missing-guide/ 11 | Also, http://unknownerror.net/2011-08/thrift-java-server-and-client-examples-50052 12 | 13 | # naturally, this all presumes you've got a JDK >= 5 installed. 14 | # I did the following on my box to get it the point where it looked like it worked) 15 | sudo apt-get install ant1.7 16 | sudo apt-get install python-dev 17 | sudo apt-get install byacc 18 | sudo apt-get install libboost-filesystem1.42.0 libboost-thread1.42.0 19 | sudo apt-get install libboost-filesystem1.42.0 libboost-thread1.42.0 libboost-system1.42.0 20 | sudo apt-get install flex 21 | sudo apt-get install libboost-dev libboost-test1.42-dev libevent-dev automake libtool flex bison pkg-config g++ 22 | sudo apt-get install automake 23 | sudo apt-get install python-dev python-twisted ruby-dev librspec-ruby rake rubygems php5-dev php5-cli libbit-vector-perl libglib2.0-dev 24 | sudo apt-get install mono-gmcs libmono-dev 25 | sudo apt-get install ghc6 cabal-install libghc6-binary-dev libghc6-network-dev libghc6-http-dev 26 | sudo apt-get install libboost-dev libboost-test1.40-dev libevent-dev automake libtool flex bison pkg-config g++ 27 | 28 | 29 | wget http://www.motorlogy.com/apache//thrift/0.7.0/thrift-0.7.0.tar.gz #download it from Apache 30 | tar zxpf thrift-0.7.0.tar.gz 31 | cd thrift-0.7.0 32 | chmod a+x configure 33 | ./configure 34 | make # assuming that goes with no problems 35 | sudo make install 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/obm/messagepack/util/TypeUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 18 | package org.springframework.obm.messagepack.util; 19 | 20 | import org.springframework.util.Assert; 21 | 22 | import java.lang.reflect.Method; 23 | import java.lang.reflect.ParameterizedType; 24 | import java.lang.reflect.Type; 25 | import java.lang.reflect.WildcardType; 26 | 27 | /** 28 | * patterned very much after {@link org.springframework.util.TypeUtils} 29 | * 30 | * @author Josh Long 31 | */ 32 | abstract public class TypeUtils { 33 | 34 | 35 | static public Class[] getGenericTypesForReturnValue(Method method) { 36 | Type t1 = method.getGenericReturnType(); 37 | if (t1 instanceof ParameterizedType) { 38 | 39 | ParameterizedType genericReturnType = (ParameterizedType) method.getGenericReturnType(); 40 | 41 | Type[] type = genericReturnType.getActualTypeArguments(); 42 | Class[] classes = new Class[type.length]; 43 | int ctr = 0; 44 | for (Type t : type) { 45 | if (!(t instanceof WildcardType)) { 46 | Assert.isInstanceOf(Class.class, t); 47 | classes[ctr++] = (Class) t; 48 | } 49 | } 50 | return classes; 51 | } 52 | return new Class[0]; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/obm/BaseMarshallerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.obm; 18 | 19 | import junit.framework.Assert; 20 | 21 | import java.io.ByteArrayInputStream; 22 | import java.io.ByteArrayOutputStream; 23 | 24 | /** 25 | * @author Josh Long 26 | */ 27 | abstract public class BaseMarshallerTest { 28 | protected Marshaller marshaller; 29 | protected Unmarshaller unmarshaller; 30 | 31 | public void setUnmarshaller(Unmarshaller unmarshaller) { 32 | Assert.assertNotNull(unmarshaller); 33 | this.unmarshaller = unmarshaller; 34 | } 35 | 36 | public void setMarshaller(Marshaller marshaller) { 37 | Assert.assertNotNull(marshaller); 38 | this.marshaller = marshaller; 39 | } 40 | 41 | 42 | protected void doTestMarshalling(Class cl, T input) throws Exception { 43 | boolean canItWriteACustomer = marshaller.supports(cl); 44 | Assert.assertTrue(canItWriteACustomer); 45 | 46 | ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream(); 47 | 48 | marshaller.marshal(input, arrayOutputStream); 49 | 50 | arrayOutputStream.flush(); 51 | arrayOutputStream.close(); 52 | 53 | byte[] bytesWritten = arrayOutputStream.toByteArray(); 54 | ByteArrayInputStream arrayInputStream = new ByteArrayInputStream(bytesWritten); 55 | T output = unmarshaller.unmarshal(cl, arrayInputStream); 56 | Assert.assertEquals(output, input); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/http/converter/obm/support/DebugClientHttpRequestInterceptor.java: -------------------------------------------------------------------------------- 1 | package org.springframework.http.converter.obm.support; 2 | 3 | import org.apache.commons.logging.Log; 4 | import org.apache.commons.logging.LogFactory; 5 | import org.springframework.http.HttpHeaders; 6 | import org.springframework.http.HttpRequest; 7 | import org.springframework.http.MediaType; 8 | import org.springframework.http.client.ClientHttpRequestExecution; 9 | import org.springframework.http.client.ClientHttpRequestInterceptor; 10 | import org.springframework.http.client.ClientHttpResponse; 11 | 12 | import java.io.IOException; 13 | import java.util.Arrays; 14 | 15 | /** 16 | *

Set on the {@link org.springframework.web.client.RestTemplate#setInterceptors(org.springframework.http.client.ClientHttpRequestInterceptor[])} 17 | * property to set tye {@link MediaType} on the client.

18 | *

19 | *

Additionally, if the {@link org.apache.commons.logging.Log#isDebugEnabled() debug is enable in Apache Comons log} 20 | * then this method will {@link Log#debug(Object)} the outbound request

21 | *

22 | * 23 | * @author Josh Long 24 | */ 25 | public class DebugClientHttpRequestInterceptor implements ClientHttpRequestInterceptor { 26 | private Log log = LogFactory.getLog(getClass()); 27 | private MediaType mediaType; 28 | 29 | public DebugClientHttpRequestInterceptor(MediaType mediaType) { 30 | this.mediaType = mediaType; 31 | } 32 | 33 | private void debug(String title, HttpHeaders headers) { 34 | if (log.isDebugEnabled()) { 35 | log.debug("============== " + title + " =============="); 36 | } 37 | for (String k : headers.keySet()) { 38 | if (log.isDebugEnabled()) { 39 | log.debug(String.format("%s = %s", k, headers.get(k))); 40 | } 41 | } 42 | } 43 | 44 | @Override 45 | public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { 46 | request.getHeaders().setAccept(Arrays.asList(this.mediaType)); 47 | debug("Request: ", request.getHeaders()); 48 | return execution.execute(request, body); 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/obm/protocolbuffers/ProtocolBuffersMarshaller.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.obm.protocolbuffers; 18 | 19 | import com.google.protobuf.GeneratedMessage; 20 | import com.google.protobuf.Message; 21 | import org.springframework.obm.support.AbstractMarshaller; 22 | import org.springframework.util.Assert; 23 | 24 | import java.io.InputStream; 25 | import java.io.OutputStream; 26 | import java.lang.reflect.Method; 27 | 28 | /** 29 | * Protocol buffers is one of the most mature serialization libraries out there at the moment. 30 | * 31 | * @author Josh Long 32 | */ 33 | public class ProtocolBuffersMarshaller extends AbstractMarshaller { 34 | 35 | @Override 36 | public boolean supports(Class clazz) { 37 | return Message.class.isAssignableFrom(clazz); 38 | } 39 | 40 | 41 | @Override 42 | public void marshal(T obj, OutputStream os) throws Exception { 43 | Assert.isTrue(obj instanceof Message, "the marshaller can only serialize subclasses of " + Message.class.getName()); 44 | Message msg = (Message) obj; 45 | os.write(msg.toByteArray()); 46 | } 47 | 48 | @Override 49 | public T unmarshal(Class clazz, InputStream source) throws Exception { 50 | Method newBuilder = clazz.getMethod("newBuilder"); 51 | Assert.isAssignable(Message.class, clazz, "the marshaller can only unmarshal subclases of " + Message.class.getName()); 52 | GeneratedMessage.Builder builder = (GeneratedMessage.Builder) newBuilder.invoke(clazz); 53 | Message msg = builder.mergeFrom(source).build(); 54 | return (T) msg; 55 | } 56 | } -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/obm/avro/crm/Customer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Autogenerated by Avro 3 | * 4 | * DO NOT EDIT DIRECTLY 5 | */ 6 | package org.springframework.obm.avro.crm; 7 | 8 | @SuppressWarnings("all") 9 | public class Customer extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord { 10 | public static final org.apache.avro.Schema SCHEMA$ = org.apache.avro.Schema.parse("{\"type\":\"record\",\"name\":\"Customer\",\"namespace\":\"org.springframework.obm.avro.crm\",\"fields\":[{\"name\":\"firstName\",\"type\":[\"string\",\"null\"]},{\"name\":\"lastName\",\"type\":[\"string\",\"null\"]},{\"name\":\"email\",\"type\":[\"string\",\"null\"]},{\"name\":\"id\",\"type\":[\"int\",\"null\"]}]}"); 11 | public java.lang.CharSequence firstName; 12 | public java.lang.CharSequence lastName; 13 | public java.lang.CharSequence email; 14 | public java.lang.Integer id; 15 | 16 | public org.apache.avro.Schema getSchema() { 17 | return SCHEMA$; 18 | } 19 | 20 | // Used by DatumWriter. Applications should not call. 21 | public java.lang.Object get(int field$) { 22 | switch (field$) { 23 | case 0: 24 | return firstName; 25 | case 1: 26 | return lastName; 27 | case 2: 28 | return email; 29 | case 3: 30 | return id; 31 | default: 32 | throw new org.apache.avro.AvroRuntimeException("Bad index"); 33 | } 34 | } 35 | 36 | // Used by DatumReader. Applications should not call. 37 | @SuppressWarnings(value = "unchecked") 38 | public void put(int field$, java.lang.Object value$) { 39 | switch (field$) { 40 | case 0: 41 | firstName = (java.lang.CharSequence) value$; 42 | break; 43 | case 1: 44 | lastName = (java.lang.CharSequence) value$; 45 | break; 46 | case 2: 47 | email = (java.lang.CharSequence) value$; 48 | break; 49 | case 3: 50 | id = (java.lang.Integer) value$; 51 | break; 52 | default: 53 | throw new org.apache.avro.AvroRuntimeException("Bad index"); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/remoting/avro/AvroServiceExporter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.remoting.avro; 17 | 18 | import org.apache.avro.ipc.ResponderRequestHandlerUtils; 19 | import org.springframework.http.MediaType; 20 | import org.springframework.util.Assert; 21 | import org.springframework.web.HttpRequestHandler; 22 | 23 | import javax.servlet.ServletException; 24 | import javax.servlet.http.HttpServletRequest; 25 | import javax.servlet.http.HttpServletResponse; 26 | import java.io.IOException; 27 | 28 | /** 29 | *

30 | * Simple implementation of {@link org.springframework.web.HttpRequestHandler} that adapts {@link org.apache.avro.ipc.ResponderServlet} 31 | *

32 | * This can be registered in any servlet container through the standard Spring web machinery. 33 | *

34 | * You do not need a ful {@link org.springframework.web.servlet.DispatcherServlet}, a {@link org.springframework.web.context.support.HttpRequestHandlerServlet} 35 | * will suffice, although it lacks the mapping support in the {@link org.springframework.web.servlet.DispatcherServlet}. 36 | * 37 | * @author Josh Long 38 | * @see org.springframework.remoting.caucho.HessianServiceExporter 39 | */ 40 | public class AvroServiceExporter extends AbstractAvroExporter implements HttpRequestHandler { 41 | 42 | private MediaType mediaType = new MediaType("avro", "binary"); 43 | 44 | public void setMediaType(MediaType mediaType) { 45 | this.mediaType = mediaType; 46 | } 47 | 48 | @Override 49 | public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 50 | Assert.notNull(this.mediaType, "the 'MEDIA_TYPE' property should not be null"); 51 | ResponderRequestHandlerUtils.handleRequest(this.mediaType, request, response, getResponder()); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/obm/thrift/ThriftCrmService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.obm.thrift; 17 | 18 | import org.apache.thrift.TException; 19 | import org.springframework.obm.thrift.crm.Crm; 20 | import org.springframework.obm.thrift.crm.Customer; 21 | import org.springframework.stereotype.Service; 22 | 23 | import java.util.Arrays; 24 | import java.util.List; 25 | import java.util.Random; 26 | 27 | /** 28 | * Simple service definition written with Thrift in mind. 29 | * 30 | * @author Josh Long 31 | */ 32 | @Service("crm") 33 | public class ThriftCrmService implements Crm.Iface { 34 | 35 | private List firstNames = Arrays.asList("Josh", "Oliver", "Costin", "Juergen", "Rod", "Mark", "Dave", "Arjen", "Keith", "Adam", "Mike", "Mario"); 36 | private List lastNames = Arrays.asList("Lee", "Loo", "Wi", "Li", "Humble", "Duong", "Kuo"); 37 | 38 | private final Random lnRandom = new Random(); 39 | private final Random fnRandom = new Random(); 40 | 41 | private String lastName() { 42 | int i = lnRandom.nextInt(lastNames.size()); 43 | return lastNames.get(i); 44 | } 45 | 46 | private String firstName() { 47 | int i = fnRandom.nextInt(firstNames.size()); 48 | return firstNames.get(i); 49 | } 50 | 51 | public Customer createCustomer(String fn, String ln, String email, int id) { 52 | return new Customer(fn, ln, email, id); 53 | } 54 | 55 | @Override 56 | public Customer createCustomer(String fn, String ln, String email) throws TException { 57 | return createCustomer(fn, ln, email, (int) (Math.random() * 2002)); 58 | } 59 | 60 | public Customer getCustomerById(int customerId) { 61 | String fn = firstName(); 62 | String ln = lastName(); 63 | return new Customer(fn, ln, fn + "@email.com", customerId); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/util/http/EndpointTestUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.util.http; 18 | 19 | import org.mortbay.jetty.Server; 20 | import org.mortbay.jetty.nio.SelectChannelConnector; 21 | import org.mortbay.jetty.servlet.Context; 22 | import org.springframework.util.Assert; 23 | 24 | /** 25 | * provides support for launching a Jetty {@link Server} instance. Users may implement {@link JettyContextConfigurationCallback} 26 | * to tailor the deployed web applications in the Jetty context as required. 27 | * 28 | * @author Josh Long 29 | * @see DispatcherServletJettyConfigurationCallback 30 | * @see Server 31 | */ 32 | abstract public class EndpointTestUtils { 33 | 34 | /** 35 | * Launches a Jetty server and then preconfigures Spring's web infrastructure and the bootstraps the 36 | * configuration object that's passed in as a parameter 37 | * 38 | * @param bindAddress the address to which to bind the server (can be null) 39 | */ 40 | static public Server serve(String bindAddress, int port, JettyContextConfigurationCallback c) throws Throwable { 41 | Server server = new Server(); 42 | SelectChannelConnector connector = new SelectChannelConnector(); 43 | connector.setLowResourceMaxIdleTime(10000); 44 | connector.setAcceptQueueSize(128); 45 | connector.setResolveNames(false); 46 | connector.setUseDirectBuffers(false); 47 | if (bindAddress != null) { 48 | connector.setHost(bindAddress); 49 | } 50 | connector.setPort(port); 51 | server.addConnector(connector); 52 | Assert.notNull(c, "the " + JettyContextConfigurationCallback.class.getSimpleName() + " instance can't be null "); 53 | c.configure(new Context(server, "/")); 54 | return server; 55 | } 56 | 57 | static public Server serve(JettyContextConfigurationCallback callback) throws Throwable { 58 | return serve(null, 8080, callback); 59 | } 60 | 61 | 62 | } 63 | -------------------------------------------------------------------------------- /obm/src/test/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # 3 | # The following properties set the logging levels and log appender. The 4 | # log4j.rootCategory variable defines the default log level and one or more 5 | # appenders. For the console, use 'S'. For the daily rolling file, use 'R'. 6 | # For an HTML formatted log, use 'H'. 7 | # 8 | # To override the default (rootCategory) log level, define a property of the 9 | # form (see below for available values): 10 | # 11 | # log4j.logger. = 12 | # 13 | # Available logger names: 14 | # TODO 15 | # 16 | # Possible Log Levels: 17 | # FATAL, ERROR, WARN, INFO, DEBUG 18 | # 19 | #------------------------------------------------------------------------------ 20 | log4j.rootCategory=INFO, S 21 | 22 | log4j.logger.org.springframework=DEBUG 23 | log4j.logger.org.w3c.tidy=FATAL 24 | 25 | #------------------------------------------------------------------------------ 26 | # 27 | # The following properties configure the console (stdout) appender. 28 | # See http://logging.apache.org/log4j/docs/api/index.html for details. 29 | # 30 | #------------------------------------------------------------------------------ 31 | log4j.appender.S = org.apache.log4j.ConsoleAppender 32 | log4j.appender.S.layout = org.apache.log4j.PatternLayout 33 | log4j.appender.S.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} %c{1} [%p] %m%n 34 | 35 | #------------------------------------------------------------------------------ 36 | # 37 | # The following properties configure the Daily Rolling File appender. 38 | # See http://logging.apache.org/log4j/docs/api/index.html for details. 39 | # 40 | #------------------------------------------------------------------------------ 41 | log4j.appender.R = org.apache.log4j.DailyRollingFileAppender 42 | log4j.appender.R.File = logs/bensApps.log 43 | log4j.appender.R.Append = true 44 | log4j.appender.R.DatePattern = '.'yyy-MM-dd 45 | log4j.appender.R.layout = org.apache.log4j.PatternLayout 46 | log4j.appender.R.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} %c{1} [%p] %m%n 47 | 48 | #------------------------------------------------------------------------------ 49 | # 50 | # The following properties configure the Rolling File appender in HTML. 51 | # See http://logging.apache.org/log4j/docs/api/index.html for details. 52 | # 53 | #------------------------------------------------------------------------------ 54 | log4j.appender.H = org.apache.log4j.RollingFileAppender 55 | log4j.appender.H.File = logs/bensApps.html 56 | log4j.appender.H.MaxFileSize = 100KB 57 | log4j.appender.H.Append = false 58 | log4j.appender.H.layout = org.apache.log4j.HTMLLayout 59 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/util/http/DispatcherServletJettyConfigurationCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.util.http; 18 | 19 | 20 | import org.mortbay.jetty.servlet.Context; 21 | import org.mortbay.jetty.servlet.ServletHolder; 22 | import org.springframework.context.annotation.Configuration; 23 | import org.springframework.util.Assert; 24 | import org.springframework.util.StringUtils; 25 | import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; 26 | import org.springframework.web.servlet.DispatcherServlet; 27 | 28 | /** 29 | * A jetty configuration callback that knows how to register Spring MVC and the {@link org.springframework.web.servlet.DispatcherServlet} 30 | * 31 | * @author Josh Long 32 | */ 33 | public class DispatcherServletJettyConfigurationCallback implements JettyContextConfigurationCallback { 34 | 35 | private Class configurationClass; 36 | 37 | private String servletPrefix; 38 | 39 | public DispatcherServletJettyConfigurationCallback(Class configurationClass) { 40 | this(configurationClass, null); 41 | } 42 | 43 | public DispatcherServletJettyConfigurationCallback(Class configurationClass, String servletPrefix) { 44 | Assert.notNull(configurationClass, "the configuration class can't be null!"); 45 | this.configurationClass = configurationClass; 46 | this.servletPrefix = StringUtils.hasText(servletPrefix) ? servletPrefix : "/*"; 47 | Assert.isTrue(this.configurationClass.getAnnotation(Configuration.class) != null, 48 | "the configuration class must have the " + Configuration.class.getName() + " annotation on it"); 49 | } 50 | 51 | @Override 52 | public void configure(Context context) throws Exception { 53 | ServletHolder holder = new ServletHolder(DispatcherServlet.class); 54 | holder.setInitParameter("contextClass", AnnotationConfigWebApplicationContext.class.getName()); 55 | holder.setInitParameter("contextConfigLocation", configurationClass.getName()); 56 | holder.setInitOrder(1); 57 | context.addServlet(holder, this.servletPrefix); 58 | } 59 | } -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/remoting/thrift/AbstractThriftExporter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.remoting.thrift; 18 | 19 | import org.apache.thrift.TProcessor; 20 | import org.springframework.beans.factory.InitializingBean; 21 | import org.springframework.obm.thrift.util.ThriftUtil; 22 | import org.springframework.remoting.support.RemoteExporter; 23 | import org.springframework.util.Assert; 24 | 25 | /** 26 | * Exports a single bean, but does not "serve" the interface over a network connection. Requires 27 | * for the {@link #serviceInterface} property a reference to the "IFace" class inside the 28 | * Thrift generated class, e.g., {@code Foo.IFace.class}. The {@link #service} itself is any POJO, 29 | * but that POJO must implement the {@link #serviceInterface}. 30 | * 31 | * @author Josh Long 32 | */ 33 | abstract public class AbstractThriftExporter extends RemoteExporter implements InitializingBean { 34 | 35 | /** 36 | * the top-level class that was generated as part of thrift compilation for a given service interface 37 | */ 38 | protected Class thriftClass; 39 | 40 | /** 41 | * handles dispatching incoming requests to the 'service' 42 | */ 43 | protected TProcessor processor; 44 | 45 | @Override 46 | public void setServiceInterface(Class serviceInterface) { 47 | super.setServiceInterface(ThriftUtil.buildServiceInterface(serviceInterface)); 48 | this.thriftClass = getServiceInterface().getEnclosingClass(); 49 | Assert.notNull(this.thriftClass, "the 'thriftClass' can't be null"); 50 | } 51 | 52 | @Override 53 | public void afterPropertiesSet() throws Exception { 54 | Class serviceInterface = getServiceInterface(); 55 | Object service = getService(); 56 | 57 | Assert.notNull(service, "the service must not be null"); 58 | Assert.notNull(serviceInterface, "the serviceInterface must not be null"); 59 | Assert.isTrue(serviceInterface.isAssignableFrom(service.getClass())); 60 | 61 | this.processor = ThriftUtil.buildProcessor(thriftClass, getServiceInterface(), getService()); 62 | 63 | } 64 | 65 | public void setProcessor(TProcessor processor) { 66 | this.processor = processor; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/remoting/jbr/TestJbossRemotingExporter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.remoting.jbr; 17 | 18 | import org.apache.commons.logging.Log; 19 | import org.apache.commons.logging.LogFactory; 20 | import org.junit.Assert; 21 | import org.junit.Test; 22 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 23 | import org.springframework.context.annotation.Bean; 24 | import org.springframework.context.annotation.Configuration; 25 | 26 | public class TestJbossRemotingExporter { 27 | 28 | private Log log = LogFactory.getLog(getClass()); 29 | 30 | @Configuration 31 | public static class ClientConfiguration { 32 | @Bean 33 | public JbossRemotingProxyFactoryBean client() { 34 | JbossRemotingProxyFactoryBean bean = new JbossRemotingProxyFactoryBean(); 35 | bean.setServiceInterface(Crm.class); 36 | return bean; 37 | } 38 | } 39 | 40 | @Configuration 41 | public static class ServerConfiguration { 42 | @Bean 43 | public CrmImpl crm() { 44 | return new CrmImpl(); 45 | } 46 | 47 | @Bean 48 | public JbossRemotingExporter exporter() { 49 | JbossRemotingExporter exporter = new JbossRemotingExporter(); 50 | exporter.setService(crm()); 51 | exporter.setServiceInterface(Crm.class); 52 | return exporter; 53 | } 54 | } 55 | 56 | @Test 57 | public void testRetreivingDataFromRpc() throws Throwable { 58 | 59 | AnnotationConfigApplicationContext client = null, server = null; 60 | 61 | try { 62 | server = new AnnotationConfigApplicationContext(ServerConfiguration.class); 63 | client = new AnnotationConfigApplicationContext(ClientConfiguration.class); 64 | Crm clientBean = client.getBean(Crm.class); 65 | 66 | long id = 8709; 67 | Customer customer = clientBean.getCustomerById(id); 68 | Assert.assertNotNull(customer); 69 | Assert.assertEquals(customer.getId(), id); 70 | 71 | if (log.isDebugEnabled()) { 72 | log.debug(customer.toString()); 73 | } 74 | } finally { 75 | if (null != client) { 76 | client.stop(); 77 | } 78 | if (null != server) { 79 | server.stop(); 80 | } 81 | } 82 | } 83 | 84 | 85 | } 86 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/obm/messagepack/support/MessagePackRegistrar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.obm.messagepack.support; 18 | 19 | import org.apache.commons.logging.Log; 20 | import org.apache.commons.logging.LogFactory; 21 | import org.msgpack.MessagePack; 22 | import org.msgpack.Template; 23 | import org.msgpack.template.builder.BeansTemplateBuilder; 24 | import org.springframework.beans.factory.InitializingBean; 25 | import org.springframework.obm.messagepack.util.ReflectionUtils; 26 | 27 | import java.util.Collection; 28 | import java.util.Collections; 29 | import java.util.HashSet; 30 | import java.util.Set; 31 | 32 | /** 33 | * the registrar can crawl classes (and their interfaces, which in turn might depend on other classes) 34 | * and register all of then with MessagePack. 35 | * 36 | * @author Josh Long 37 | */ 38 | public class MessagePackRegistrar implements InitializingBean { 39 | private BeansTemplateBuilder beansTemplateBuilder = new BeansTemplateBuilder(); 40 | 41 | private boolean serializeJavaBeanProperties = true; 42 | 43 | private Set classes = new HashSet(); 44 | 45 | private Log log = LogFactory.getLog(getClass()); 46 | 47 | public void setSerializeJavaBeanProperties(boolean serializeJavaBeanProperties) { 48 | this.serializeJavaBeanProperties = serializeJavaBeanProperties; 49 | } 50 | 51 | public void registerClasses(Collection clzz) { 52 | classes.addAll(clzz); 53 | } 54 | 55 | public void registerClasses(Class... clazz) { 56 | Collections.addAll(classes, clazz); 57 | } 58 | 59 | public void discoverClasses(Class clazzInterface) { 60 | ReflectionUtils.crawlJavaBeanObjectGraph(clazzInterface, new ReflectionUtils.ClassTraversalCallback() { 61 | @Override 62 | public void doWithClass(Class foundClass) { 63 | if (log.isDebugEnabled()) { 64 | log.debug("found " + foundClass.getName() + "."); 65 | } 66 | 67 | if (ReflectionUtils.isUninterestingClass(foundClass)) { 68 | return; 69 | } 70 | if (!classes.contains(foundClass)) { 71 | classes.add(foundClass); 72 | } 73 | 74 | } 75 | }); 76 | } 77 | 78 | protected void register() { 79 | for (Class foundClass : this.classes) { 80 | if (serializeJavaBeanProperties) { 81 | Template template = beansTemplateBuilder.buildTemplate(foundClass); 82 | MessagePack.register(foundClass, template); 83 | } else { 84 | MessagePack.register(foundClass); 85 | } 86 | } 87 | } 88 | 89 | @Override 90 | public void afterPropertiesSet() throws Exception { 91 | register(); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/util/jms/JmsIntegrationTestUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.util.jms; 18 | 19 | import org.apache.activemq.ActiveMQConnectionFactory; 20 | import org.apache.activemq.broker.BrokerService; 21 | import org.apache.activemq.broker.TransportConnector; 22 | import org.apache.commons.logging.Log; 23 | import org.apache.commons.logging.LogFactory; 24 | import org.junit.Assert; 25 | import org.springframework.jms.core.JmsTemplate; 26 | import org.springframework.jms.support.converter.obm.MarshallingMessageConverter; 27 | import org.springframework.obm.Marshaller; 28 | 29 | /** 30 | * Supports integration tests with an embedded ActiveMQ instance. 31 | * 32 | * @author Josh Long 33 | */ 34 | abstract public class JmsIntegrationTestUtils { 35 | 36 | static private Log log = LogFactory.getLog(JmsIntegrationTestUtils.class); 37 | 38 | /** 39 | * during the execution of this callback, a JMS broker will be available and the {@link JmsTemplate} required to 40 | * connect to that JMS broker will be provided as a parameter to this 41 | * class's {@link JmsBrokerExecutionCallback#doWithActiveMq(org.apache.activemq.broker.BrokerService, org.springframework.jms.core.JmsTemplate)} 42 | */ 43 | public static interface JmsBrokerExecutionCallback { 44 | void doWithActiveMq(BrokerService brokerService, JmsTemplate jmsTemplate) throws Throwable; 45 | } 46 | 47 | public static void startAndConnectToJmsBroker(Class clzzForPayload, Marshaller m, JmsBrokerExecutionCallback callback) throws Throwable { 48 | Assert.assertNotNull("the " + JmsBrokerExecutionCallback.class.getName() + "can not be null", callback); 49 | String destinationUrl = "tcp://localhost:61617"; 50 | BrokerService broker = new BrokerService(); 51 | TransportConnector connector = broker.addConnector(destinationUrl); 52 | broker.start(); 53 | while (!broker.isStarted()) { 54 | Thread.sleep(500); 55 | } 56 | ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(destinationUrl); 57 | MarshallingMessageConverter converter = new MarshallingMessageConverter(clzzForPayload, m); 58 | JmsTemplate jmsTemplate = new JmsTemplate(activeMQConnectionFactory); 59 | converter.setPayloadClass(clzzForPayload); 60 | jmsTemplate.setMessageConverter(converter); 61 | jmsTemplate.afterPropertiesSet(); 62 | 63 | try { 64 | callback.doWithActiveMq(broker, jmsTemplate); 65 | } catch (AssertionError ae) { 66 | throw ae; 67 | } catch (Throwable th) { 68 | if (log.isErrorEnabled()) { 69 | log.error("execution of jms session failed.", th); 70 | } 71 | } finally { 72 | connector.stop(); 73 | broker.stop(); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/remoting/messagepack/EventLoopFactoryBean.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.remoting.messagepack; 18 | 19 | import org.msgpack.rpc.loop.EventLoop; 20 | import org.springframework.beans.factory.DisposableBean; 21 | import org.springframework.beans.factory.FactoryBean; 22 | import org.springframework.beans.factory.InitializingBean; 23 | 24 | import java.util.concurrent.ExecutorService; 25 | import java.util.concurrent.Executors; 26 | import java.util.concurrent.ScheduledExecutorService; 27 | 28 | /** 29 | * @author Josh Long 30 | */ 31 | public class EventLoopFactoryBean implements FactoryBean, InitializingBean, DisposableBean { 32 | private volatile boolean setup = false; 33 | private ExecutorService workerExecutor; 34 | private ExecutorService ioExecutor; 35 | private ScheduledExecutorService scheduledExecutorService; 36 | private EventLoop eventLoop; 37 | 38 | @Override 39 | public EventLoop getObject() throws Exception { 40 | afterPropertiesSet(); 41 | return this.eventLoop; 42 | } 43 | 44 | @Override 45 | public Class getObjectType() { 46 | return EventLoop.class; 47 | } 48 | 49 | @Override 50 | public boolean isSingleton() { 51 | return false; 52 | } 53 | 54 | public void setWorkerExecutor(ExecutorService workerExecutor) { 55 | this.workerExecutor = workerExecutor; 56 | } 57 | 58 | public void setIoExecutor(ExecutorService ioExecutor) { 59 | this.ioExecutor = ioExecutor; 60 | } 61 | 62 | public void setScheduledExecutorService(ScheduledExecutorService scheduledExecutorService) { 63 | this.scheduledExecutorService = scheduledExecutorService; 64 | } 65 | 66 | private int ioThreads = 10; 67 | private int workerThreads = 10; 68 | private int scheduledThreads = 10; 69 | 70 | @Override 71 | public void afterPropertiesSet() throws Exception { 72 | 73 | if (this.setup) { 74 | return; 75 | } 76 | 77 | if (this.workerExecutor == null) { 78 | this.workerExecutor = Executors.newFixedThreadPool(this.workerThreads); 79 | } 80 | 81 | if (this.ioExecutor == null) { 82 | this.ioExecutor = Executors.newFixedThreadPool(this.ioThreads); 83 | } 84 | 85 | if (this.scheduledExecutorService == null) { 86 | this.scheduledExecutorService = Executors.newScheduledThreadPool(this.scheduledThreads); 87 | } 88 | 89 | this.eventLoop = EventLoop.start(this.workerExecutor, this.ioExecutor, this.scheduledExecutorService); 90 | 91 | this.setup = true; 92 | 93 | } 94 | 95 | 96 | @Override 97 | public void destroy() throws Exception { 98 | eventLoop.shutdown(); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/obm/messagepack/MessagePackMarshaller.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.obm.messagepack; 18 | 19 | import org.msgpack.MessagePack; 20 | import org.msgpack.Template; 21 | import org.msgpack.template.builder.BeansTemplateBuilder; 22 | import org.springframework.beans.factory.InitializingBean; 23 | import org.springframework.obm.support.AbstractMarshaller; 24 | import org.springframework.util.Assert; 25 | 26 | import java.io.InputStream; 27 | import java.io.OutputStream; 28 | import java.util.Set; 29 | import java.util.concurrent.CopyOnWriteArraySet; 30 | 31 | 32 | /** 33 | * Implementation of the marshaler and unmarshaller contracts that delegates to MessagePack for serialization 34 | * 35 | * @author Josh Long 36 | */ 37 | public class MessagePackMarshaller extends AbstractMarshaller implements InitializingBean { 38 | 39 | private BeansTemplateBuilder beansTemplateBuilder = new BeansTemplateBuilder(); 40 | 41 | private boolean serializeJavaBeanProperties = true; 42 | 43 | private Set> messagePackClasses = new CopyOnWriteArraySet>(); 44 | 45 | public void setSerializeJavaBeanProperties(boolean serializeJavaBeanProperties) { 46 | this.serializeJavaBeanProperties = serializeJavaBeanProperties; 47 | } 48 | 49 | @Override 50 | public void afterPropertiesSet() throws Exception { 51 | if (!serializeJavaBeanProperties) { 52 | if (log.isDebugEnabled()) { 53 | log.debug("the 'serializeJavaBeanProperties' property has been set to false, " + 54 | "which means that all POJOs must expose public variables to properly be serialized."); 55 | } 56 | } 57 | } 58 | 59 | @Override 60 | public void marshal(T obj, OutputStream os) throws Exception { 61 | Assert.isTrue(messagePackSupports(obj.getClass()), "the class must be registered"); 62 | MessagePack.pack(os, obj); 63 | } 64 | 65 | @Override 66 | public boolean supports(Class clazz) { 67 | return messagePackSupports(clazz); 68 | } 69 | 70 | @Override 71 | public T unmarshal(Class clazz, InputStream source) throws Exception { 72 | Assert.isTrue(messagePackSupports(clazz), "the class must be registered"); 73 | return MessagePack.unpack(source, clazz); 74 | } 75 | 76 | protected boolean messagePackSupports(Class clazz) { 77 | 78 | if (messagePackClasses.contains(clazz)) { 79 | return true; 80 | } 81 | 82 | // otherwise, register it 83 | messagePackClasses.add(clazz); 84 | 85 | if (serializeJavaBeanProperties) { 86 | Template template = beansTemplateBuilder.buildTemplate(clazz); 87 | MessagePack.register(clazz, template); 88 | } else { 89 | MessagePack.register(clazz); 90 | } 91 | 92 | return true; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/remoting/avro/TestServiceExportAndConsumption.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.remoting.avro; 18 | 19 | import junit.framework.Assert; 20 | import org.apache.avro.AvroRemoteException; 21 | import org.apache.commons.lang.builder.ToStringBuilder; 22 | import org.apache.commons.logging.Log; 23 | import org.apache.commons.logging.LogFactory; 24 | import org.junit.After; 25 | import org.junit.Test; 26 | import org.springframework.obm.avro.crm.Crm; 27 | import org.springframework.obm.avro.crm.Customer; 28 | import org.springframework.remoting.avro.clients.SaslTransceiverCreationCallback; 29 | import org.springframework.remoting.avro.servers.SaslServerCreationCallback; 30 | import org.springframework.util.ClassUtils; 31 | 32 | import java.util.Random; 33 | 34 | /** 35 | * @author Josh Long 36 | */ 37 | public class TestServiceExportAndConsumption { 38 | 39 | Log log = LogFactory.getLog(getClass()); 40 | SaslTransceiverCreationCallback transceiverCreationCallback = new SaslTransceiverCreationCallback(); 41 | SaslServerCreationCallback serverCreationCallback = new SaslServerCreationCallback(); 42 | AvroExporter avroExporter; 43 | 44 | static class MyCrm implements Crm { 45 | 46 | static private Random randomIdGenerator = new Random(); 47 | 48 | @Override 49 | public Customer createCustomer(CharSequence fn, CharSequence ln, CharSequence email) throws AvroRemoteException { 50 | Customer c = new Customer(); 51 | c.email = email; 52 | c.lastName = ln; 53 | c.firstName = fn; 54 | c.id = randomIdGenerator.nextInt(); 55 | return c; 56 | } 57 | } 58 | 59 | @Test 60 | public void testCreatingAServer() throws Throwable { 61 | 62 | MyCrm crmImpl = new MyCrm(); 63 | 64 | avroExporter = new AvroExporter(); 65 | avroExporter.setService(crmImpl); 66 | avroExporter.setServiceInterface(Crm.class); 67 | avroExporter.setServerCreationCallback(serverCreationCallback); 68 | avroExporter.setBeanClassLoader(ClassUtils.getDefaultClassLoader()); 69 | avroExporter.afterPropertiesSet(); 70 | avroExporter.start(); 71 | 72 | AvroProxyFactoryBean proxyFactoryBean = new AvroProxyFactoryBean(); 73 | proxyFactoryBean.setServiceInterface(Crm.class); 74 | proxyFactoryBean.setTransceiverCreationCallback(transceiverCreationCallback); 75 | proxyFactoryBean.afterPropertiesSet(); 76 | Crm crmClient = proxyFactoryBean.getObject(); 77 | Customer customer = crmClient.createCustomer("Josh", "Long", "email@email.com"); 78 | if (log.isDebugEnabled()) { 79 | log.debug("received result " + ToStringBuilder.reflectionToString(customer)); 80 | } 81 | Assert.assertNotNull(customer); 82 | } 83 | 84 | @After 85 | public void stop() throws Throwable { 86 | Assert.assertTrue(avroExporter != null); 87 | avroExporter.stop(); 88 | } 89 | 90 | 91 | } 92 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/obm/avro/support/EncoderFactoryBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.obm.avro.support; 17 | 18 | import org.apache.avro.Schema; 19 | import org.apache.avro.io.BinaryEncoder; 20 | import org.apache.avro.io.Encoder; 21 | import org.apache.avro.io.EncoderFactory; 22 | import org.springframework.util.Assert; 23 | 24 | import java.io.OutputStream; 25 | 26 | /** 27 | * Convenience class to build an {@link Encoder} 28 | * 29 | * @author Josh Long 30 | */ 31 | public class EncoderFactoryBuilder { 32 | private final static ThreadLocal encoderThreadLocal = new ThreadLocal(); 33 | private final EncoderFactory encoderFactory = new EncoderFactory(); 34 | private OutputStream outputStream; 35 | private boolean useBinary = true; 36 | private boolean validate = false; 37 | private boolean useJson = false; 38 | private Schema schema; 39 | 40 | public EncoderFactoryBuilder setUseBinary(boolean useBinary) { 41 | this.useBinary = useBinary; 42 | return this; 43 | } 44 | 45 | public EncoderFactoryBuilder setValidate(boolean validate) { 46 | this.validate = validate; 47 | return this; 48 | } 49 | 50 | public EncoderFactoryBuilder setUseJson(boolean useJson) { 51 | this.useJson = useJson; 52 | return this; 53 | } 54 | 55 | public EncoderFactoryBuilder setSchema(Schema schema) { 56 | this.schema = schema; 57 | return this; 58 | } 59 | 60 | public EncoderFactoryBuilder setOutputStream(OutputStream outputStream) { 61 | this.outputStream = outputStream; 62 | return this; 63 | } 64 | 65 | protected Encoder build(Encoder reuse) throws Exception { 66 | Encoder encoder = null; 67 | 68 | if (useBinary) { 69 | Assert.notNull(this.outputStream, "you've selected to use a binary encoder. Please provide an output stream to encode to by setting the 'outputStream' property"); 70 | encoder = encoderFactory.binaryEncoder(this.outputStream, (BinaryEncoder) reuse); 71 | } else if (useJson) { 72 | Assert.notNull(this.outputStream, "you've selected to use a JSON encoder. Please provide an output stream to encode to by setting the 'outputStream' property"); 73 | encoder = encoderFactory.jsonEncoder(this.schema, this.outputStream); 74 | } 75 | Assert.notNull(encoder, "could not build an encoder. Did you set both 'useJson' and 'useBinary' to false?"); 76 | if (validate) { 77 | Assert.notNull(this.schema, "you've selected to validate. Please provide a target schema by setting the 'schema' property"); 78 | encoder = encoderFactory.validatingEncoder(this.schema, encoder); 79 | } 80 | return encoder; 81 | } 82 | 83 | 84 | protected Encoder buildThreadAwareEncoder() throws Exception { 85 | Encoder encoder = encoderThreadLocal.get(); 86 | encoderThreadLocal.set(build(encoder)); 87 | return encoderThreadLocal.get(); 88 | } 89 | 90 | public Encoder build() throws Exception { 91 | return buildThreadAwareEncoder(); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/remoting/avro/servers/SaslServerCreationCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.remoting.avro.servers; 17 | 18 | import org.apache.avro.ipc.Responder; 19 | import org.apache.avro.ipc.SaslSocketServer; 20 | import org.apache.avro.ipc.Server; 21 | import org.springframework.util.Assert; 22 | import org.springframework.util.StringUtils; 23 | 24 | import javax.security.auth.callback.CallbackHandler; 25 | import java.io.IOException; 26 | import java.net.InetSocketAddress; 27 | import java.util.HashMap; 28 | import java.util.Map; 29 | 30 | /** 31 | *

32 | * {@link org.springframework.remoting.avro.AvroExporter} that delegates to Avro's {@link org.apache.avro.ipc.SaslSocketServer}, 33 | * which in turn implements SASL - the simple authentication and security layer. 34 | *

35 | *

See http://en.wikipedia.org/wiki/Simple_Authentication_and_Security_Layer for details. 36 | * 37 | * @author Josh Long 38 | * @see org.springframework.remoting.avro.AvroExporter 39 | */ 40 | public class SaslServerCreationCallback implements ServerCreationCallback { 41 | 42 | private CallbackHandler callbackHandler; 43 | private String saslMechanism; 44 | private String saslProtocol; 45 | private String serverName; 46 | private Map saslProperties; 47 | 48 | public void setCallbackHandler(CallbackHandler callbackHandler) { 49 | this.callbackHandler = callbackHandler; 50 | } 51 | 52 | public void setSaslMechanism(String saslMechanism) { 53 | this.saslMechanism = saslMechanism; 54 | } 55 | 56 | public void setSaslProtocol(String saslProtocol) { 57 | this.saslProtocol = saslProtocol; 58 | } 59 | 60 | public void setServerName(String serverName) { 61 | this.serverName = serverName; 62 | } 63 | 64 | public void setSaslProperties(Map saslProperties) { 65 | this.saslProperties = saslProperties; 66 | } 67 | 68 | 69 | @Override 70 | public Server buildServer(InetSocketAddress address, Responder responder) throws Exception { 71 | try { 72 | boolean fullSasl = StringUtils.hasText(this.saslMechanism) || StringUtils.hasText(this.saslProtocol) || 73 | StringUtils.hasText(serverName) || callbackHandler != null || saslProperties != null; 74 | SaslSocketServer saslSocketServer; 75 | if (fullSasl) { 76 | if (saslProperties == null) { 77 | saslProperties = new HashMap(); 78 | } 79 | saslSocketServer = new SaslSocketServer(responder, address, saslMechanism, saslProtocol, serverName, saslProperties, callbackHandler); 80 | } else { 81 | // default, anonymous SASL (nothing wrong with that!) 82 | saslSocketServer = new SaslSocketServer(responder, address); 83 | } 84 | Assert.notNull(saslSocketServer, "we experienced an error building the server"); 85 | return saslSocketServer; 86 | } catch (IOException e) { 87 | throw new RuntimeException(e); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/obm/thrift/ThriftMarshaller.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.obm.thrift; 18 | 19 | import org.apache.thrift.TBase; 20 | import org.apache.thrift.TDeserializer; 21 | import org.apache.thrift.TSerializer; 22 | import org.springframework.beans.factory.InitializingBean; 23 | import org.springframework.obm.support.AbstractMarshaller; 24 | import org.springframework.oxm.XmlMappingException; 25 | import org.springframework.util.Assert; 26 | import org.springframework.util.FileCopyUtils; 27 | 28 | import java.io.IOException; 29 | import java.io.InputStream; 30 | import java.io.OutputStream; 31 | 32 | /** 33 | * implementation of {@link org.springframework.obm.Marshaller} and {@link org.springframework.obm.Unmarshaller} 34 | * that supports Apache Thrift (http://thrift.apache.org/). 35 | * 36 | * @author Josh Long 37 | */ 38 | public class ThriftMarshaller extends AbstractMarshaller implements InitializingBean { 39 | 40 | private TSerializer serializer; 41 | 42 | private TDeserializer deserializer; 43 | 44 | public void setDeserializer(TDeserializer deserializer) { 45 | this.deserializer = deserializer; 46 | } 47 | 48 | public void setSerializer(TSerializer serializer) { 49 | this.serializer = serializer; 50 | } 51 | 52 | @Override 53 | public boolean supports(Class clazz) { 54 | return true; 55 | } 56 | 57 | @Override 58 | public void marshal(T obj, OutputStream os) throws IOException, XmlMappingException { 59 | Assert.isInstanceOf(TBase.class, obj); 60 | try { 61 | byte[] bytesForObj = this.serializer.serialize(obj); 62 | FileCopyUtils.copy(bytesForObj, os); 63 | } catch (Throwable e) { 64 | if (log.isErrorEnabled()) { 65 | log.error("something occurred when trying to TSerializer#serialize() the response", e); 66 | } 67 | throw new RuntimeException(e); 68 | } 69 | } 70 | 71 | @Override 72 | public T unmarshal(Class clazz, InputStream source) throws IOException, XmlMappingException { 73 | Assert.isTrue(TBase.class.isAssignableFrom(clazz), "the request payload must be a subclas of TBase"); 74 | try { 75 | T obj = clazz.newInstance(); 76 | 77 | byte[] bytes = FileCopyUtils.copyToByteArray(source); 78 | 79 | this.deserializer.deserialize(obj, bytes); 80 | 81 | return obj; 82 | } catch (Throwable e) { 83 | if (log.isErrorEnabled()) { 84 | log.error("something occurred when trying to TDeserializer#deserialize() the incoming request", e); 85 | } 86 | throw new RuntimeException(e); 87 | } 88 | } 89 | 90 | 91 | @Override 92 | public void afterPropertiesSet() throws Exception { 93 | if (serializer == null) { 94 | this.serializer = new TSerializer(); 95 | } 96 | 97 | if (deserializer == null) { 98 | this.deserializer = new TDeserializer(); 99 | } 100 | } 101 | } 102 | 103 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/remoting/messagepack/Cat.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.remoting.messagepack; 18 | 19 | import org.springframework.core.style.ToStringCreator; 20 | 21 | import java.util.HashSet; 22 | import java.util.Set; 23 | 24 | /** 25 | * Dummy entity with state to test RPC withc complex objects 26 | * 27 | * @author Josh Long 28 | */ 29 | public class Cat { 30 | 31 | private Set humans = new HashSet(); 32 | public Set friends = new HashSet(); 33 | public String name; 34 | public int age; 35 | 36 | public void addHuman(Human human) { 37 | this.humans.add(human); 38 | } 39 | 40 | public Set getHumans() { 41 | return humans; 42 | } 43 | 44 | public void setHumans(Set humans) { 45 | this.humans = humans; 46 | } 47 | 48 | public Set getFriends() { 49 | return friends; 50 | } 51 | 52 | public void setFriends(Set friends) { 53 | this.friends = friends; 54 | } 55 | 56 | public void addFriend(Cat c) { 57 | this.friends.add(c); 58 | } 59 | 60 | public Cat(String name, int age) { 61 | this.name = name; 62 | this.age = age; 63 | } 64 | 65 | public Cat() { 66 | } 67 | 68 | public String getName() { 69 | return name; 70 | } 71 | 72 | public void setName(String name) { 73 | this.name = name; 74 | } 75 | 76 | public int getAge() { 77 | return age; 78 | } 79 | 80 | public void setAge(int age) { 81 | this.age = age; 82 | } 83 | 84 | public String toString() { 85 | return new ToStringCreator(this) 86 | .append("friends", this.getFriends()) 87 | .append("name", this.getName()) 88 | .append("age", this.getAge()) 89 | .append("humans", this.getHumans()) 90 | .toString(); 91 | } 92 | 93 | @Override 94 | public boolean equals(Object o) { 95 | if (this == o) { 96 | return true; 97 | } 98 | if (o == null || getClass() != o.getClass()) { 99 | return false; 100 | } 101 | 102 | Cat cat = (Cat) o; 103 | 104 | if (age != cat.age) { 105 | return false; 106 | } 107 | if (friends != null ? !friends.equals(cat.friends) : cat.friends != null) { 108 | return false; 109 | } 110 | if (humans != null ? !humans.equals(cat.humans) : cat.humans != null) { 111 | return false; 112 | } 113 | if (name != null ? !name.equals(cat.name) : cat.name != null) { 114 | return false; 115 | } 116 | 117 | return true; 118 | } 119 | 120 | @Override 121 | public int hashCode() { 122 | int result = humans != null ? humans.hashCode() : 0; 123 | result = 31 * result + (friends != null ? friends.hashCode() : 0); 124 | result = 31 * result + (name != null ? name.hashCode() : 0); 125 | result = 31 * result + age; 126 | return result; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/obm/thrift/util/ThriftUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.obm.thrift.util; 18 | 19 | import org.apache.thrift.TProcessor; 20 | import org.springframework.util.Assert; 21 | import org.springframework.util.ClassUtils; 22 | 23 | import java.lang.reflect.Constructor; 24 | 25 | /** 26 | * utility methods common to multiple classes in the Thrift support 27 | * 28 | * @author Josh Long 29 | */ 30 | abstract public class ThriftUtil { 31 | /** 32 | * string to find the {@link TProcessor} implementation inside the Thrift class 33 | */ 34 | public static String PROCESSOR_NAME = "$Processor"; 35 | 36 | /** 37 | * String to find interface of the class inside the Thrift service that we should bind this service to publicly 38 | */ 39 | public static String IFACE_NAME = "$Iface"; 40 | 41 | /** 42 | * The client and the server will both attempt to bind to this port, first. 43 | *

44 | * If you override the port in either the client or the server, be sure to change the other! 45 | */ 46 | public static int DEFAULT_PORT = 1995; 47 | 48 | public static Class buildServiceInterface(Class serviceInterface) { 49 | if (serviceInterface.isInterface()) { 50 | String iFaceNameConvention = serviceInterface.getName(); 51 | if (iFaceNameConvention.contains(IFACE_NAME)) { 52 | Class clzz = serviceInterface.getEnclosingClass(); 53 | Assert.notNull(clzz, "the enclosing class can not be null"); 54 | return (serviceInterface); 55 | } 56 | } else if (!serviceInterface.isInterface()) { 57 | Class iface = ThriftUtil.getThriftServiceInnerClassOrNull(serviceInterface, IFACE_NAME, true); 58 | Assert.notNull(iface, "the service interface was not found, but is required"); 59 | return (iface); 60 | } 61 | return null; 62 | } 63 | 64 | public static Class getThriftServiceInnerClassOrNull(Class thriftServiceClass, String match, boolean isInterface) { 65 | Class[] declaredClasses = thriftServiceClass.getDeclaredClasses(); 66 | 67 | for (Class declaredClass : declaredClasses) { 68 | if (declaredClass.isInterface()) { 69 | if (isInterface && declaredClass.getName().contains(match)) { 70 | return declaredClass; 71 | } 72 | } else { 73 | if (!isInterface && declaredClass.getName().contains(match)) { 74 | return declaredClass; 75 | } 76 | } 77 | } 78 | return null; 79 | } 80 | 81 | @SuppressWarnings("unchecked") 82 | public static TProcessor buildProcessor(Class thriftClass, Class svcInterface, Object service) throws Exception { 83 | Class processorClass = (Class) getThriftServiceInnerClassOrNull(thriftClass, PROCESSOR_NAME, false); 84 | Assert.notNull(processorClass, "the processor class must not be null"); 85 | Constructor constructor = ClassUtils.getConstructorIfAvailable(processorClass, svcInterface); 86 | Assert.notNull(constructor); 87 | Object newlyCreatedProcessorBean = constructor.newInstance(service); 88 | Assert.notNull(newlyCreatedProcessorBean); 89 | Assert.isInstanceOf(TProcessor.class, newlyCreatedProcessorBean); 90 | return (TProcessor) newlyCreatedProcessorBean; 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/remoting/avro/AvroExporter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.remoting.avro; 17 | 18 | 19 | import org.apache.avro.ipc.Server; 20 | import org.springframework.beans.factory.InitializingBean; 21 | import org.springframework.context.SmartLifecycle; 22 | import org.springframework.remoting.avro.servers.NettyServerCreationCallback; 23 | import org.springframework.remoting.avro.servers.ServerCreationCallback; 24 | import org.springframework.remoting.support.RemoteExporter; 25 | import org.springframework.util.Assert; 26 | 27 | import java.net.InetSocketAddress; 28 | 29 | /** 30 | * {@link RemoteExporter} for Avro's {@link org.apache.avro.Protocol protocols}. 31 | * This {@link RemoteExporter} builds an instance of Avro's {@link Server}, and then starts it up 32 | * and configures it to expose your service bean. If you would rather let a web container 33 | * handle the server duties, then use the {@link AvroServiceExporter}, which can be used in any 34 | * {@link org.springframework.web.context.WebApplicationContext} 35 | * 36 | * @author Josh Long 37 | * @see AvroServiceExporter 38 | */ 39 | public class AvroExporter extends AbstractAvroExporter implements InitializingBean, SmartLifecycle { 40 | 41 | private volatile boolean running = false; 42 | private final Object monitor = new Object(); 43 | private volatile boolean setup = false; 44 | private Server server; 45 | protected InetSocketAddress inetSocketAddress; 46 | private ServerCreationCallback serverCreationCallback; 47 | protected int port = 2003; 48 | 49 | public void setServerCreationCallback(ServerCreationCallback serverCreationCallback) { 50 | this.serverCreationCallback = serverCreationCallback; 51 | } 52 | 53 | public void setInetSocketAddress(InetSocketAddress inetSocketAddress) { 54 | this.inetSocketAddress = inetSocketAddress; 55 | } 56 | 57 | public void setPort(int port) { 58 | this.port = port; 59 | } 60 | 61 | @Override 62 | public final void afterPropertiesSet() throws Exception { 63 | synchronized (this.monitor) { 64 | if (setup) { 65 | return; 66 | } 67 | 68 | if (inetSocketAddress == null) { 69 | Assert.isTrue(port > 0, "the port must be greater than 0"); 70 | inetSocketAddress = new InetSocketAddress(this.port); 71 | } 72 | 73 | if (this.serverCreationCallback == null) { 74 | serverCreationCallback = new NettyServerCreationCallback(); 75 | } 76 | 77 | server = this.serverCreationCallback.buildServer(this.inetSocketAddress, getResponder()); 78 | Assert.notNull(this.server, "the server was not properly constructed!"); 79 | setup = true; 80 | } 81 | } 82 | 83 | @Override 84 | public boolean isAutoStartup() { 85 | return true; 86 | } 87 | 88 | @Override 89 | public void stop() { 90 | this.running = false; 91 | } 92 | 93 | @Override 94 | public void stop(Runnable callback) { 95 | stop(); 96 | if (callback != null) { 97 | callback.run(); 98 | } 99 | } 100 | 101 | @Override 102 | public void start() { 103 | Assert.notNull(this.server, "the service is null"); 104 | server.start(); 105 | running = true; 106 | } 107 | 108 | @Override 109 | public boolean isRunning() { 110 | return running; 111 | } 112 | 113 | @Override 114 | public int getPhase() { 115 | return 0; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/remoting/messagepack/DefaultEchoService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.remoting.messagepack; 18 | 19 | import org.apache.commons.logging.Log; 20 | import org.apache.commons.logging.LogFactory; 21 | import org.springframework.beans.factory.InitializingBean; 22 | 23 | import java.util.concurrent.ExecutorService; 24 | import java.util.concurrent.Executors; 25 | 26 | /** 27 | * @author Josh Long 28 | */ 29 | public class DefaultEchoService implements EchoService, CatService { 30 | 31 | private ExecutorService executor = Executors.newSingleThreadExecutor(); 32 | 33 | private Log log = LogFactory.getLog(getClass()); 34 | 35 | @Override 36 | public String alarm(String msg) { 37 | return (msg == null ? "" : msg).toUpperCase() + "!!"; 38 | } 39 | 40 | public DefaultEchoService() { 41 | if (executor instanceof InitializingBean) { 42 | try { 43 | ((InitializingBean) executor).afterPropertiesSet(); 44 | } catch (Exception e) { 45 | log.error(e); 46 | throw new RuntimeException(e); 47 | } 48 | } 49 | } 50 | 51 | @Override 52 | public Cat fetch() { 53 | Cat garfield = new Cat("Garfield", 53); 54 | Cat nermel = new Cat("Nermel", 12); 55 | Cat george = new Cat("George", 42); 56 | garfield.addFriend(nermel); 57 | garfield.addFriend(george); 58 | 59 | Human john = new Human("John"); 60 | Human mary = new Human("Mary"); 61 | 62 | garfield.addHuman(john); 63 | garfield.addHuman(mary); 64 | 65 | return garfield; 66 | } 67 | 68 | /** 69 | * nb: this is not part of the interface, but MessagePack will attempt to call it if it's available. 70 | *

71 | * The {@link org.msgpack.rpc.Request} parameter's used to give the callee a chance to handle the request asynchronously or to leverage the error handling mechanism. 72 | * 73 | * @param request object required to facilitate communication 74 | * @param in the string to send back 75 | */ 76 | public void hello(final org.msgpack.rpc.Request request, final String in) { 77 | executor.submit(new Runnable() { 78 | @Override 79 | public void run() { 80 | try { 81 | long time = 2; 82 | Thread.sleep(time * 1000); 83 | if (log.isDebugEnabled()) { 84 | log.debug("sleeping for " + time + "s"); 85 | } 86 | request.sendResult("Hello, " + in); 87 | } catch (Throwable thro) { 88 | if (log.isErrorEnabled()) { 89 | log.error(thro); 90 | } 91 | } 92 | } 93 | }); 94 | } 95 | 96 | public void fetchCat(final org.msgpack.rpc.Request request) { 97 | executor.submit(new Runnable() { 98 | @Override 99 | public void run() { 100 | try { 101 | Thread.sleep(3 * 1000); 102 | Cat cat = fetch(); 103 | request.sendResult(cat); 104 | } catch (Throwable thro) { 105 | if (log.isErrorEnabled()) { 106 | log.error(thro); 107 | } 108 | } 109 | } 110 | }); 111 | } 112 | 113 | @Override 114 | public String echo(String in) { 115 | return "No, " + in; 116 | } 117 | 118 | public void setExecutor(ExecutorService executor) { 119 | this.executor = executor; 120 | } 121 | } -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/http/converter/obm/MarshallingHttpMessageConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.http.converter.obm; 18 | 19 | import org.springframework.beans.factory.InitializingBean; 20 | import org.springframework.http.HttpInputMessage; 21 | import org.springframework.http.HttpOutputMessage; 22 | import org.springframework.http.MediaType; 23 | import org.springframework.http.converter.AbstractHttpMessageConverter; 24 | import org.springframework.http.converter.HttpMessageNotReadableException; 25 | import org.springframework.http.converter.HttpMessageNotWritableException; 26 | import org.springframework.obm.Marshaller; 27 | import org.springframework.obm.Unmarshaller; 28 | import org.springframework.util.Assert; 29 | 30 | import java.io.IOException; 31 | import java.io.InputStream; 32 | import java.io.OutputStream; 33 | import java.util.List; 34 | 35 | /** 36 | * The idea is that this class wil do the work that all of other defintions do because, essentially, their only differentiator is that 37 | * they do project-specific IO, which the {@link Marshaller} and {@link Unmarshaller} encapsulate nicely. 38 | * 39 | * @author Josh Long 40 | * @see org.springframework.http.converter.HttpMessageConverter 41 | */ 42 | public class MarshallingHttpMessageConverter extends AbstractHttpMessageConverter implements InitializingBean { 43 | 44 | private Marshaller marshaller; 45 | 46 | private Unmarshaller unmarshaller; 47 | 48 | public MarshallingHttpMessageConverter(Marshaller marshaller) { 49 | Assert.isInstanceOf(Unmarshaller.class, marshaller); 50 | this.marshaller = marshaller; 51 | this.unmarshaller = (Unmarshaller) marshaller; 52 | } 53 | 54 | public MarshallingHttpMessageConverter(Marshaller marshaller, Unmarshaller unmarshaller) { 55 | this.unmarshaller = unmarshaller; 56 | this.marshaller = marshaller; 57 | } 58 | 59 | public void setMarshaller(Marshaller marshaller) { 60 | this.marshaller = marshaller; 61 | } 62 | 63 | public void setUnmarshaller(Unmarshaller unmarshaller) { 64 | this.unmarshaller = unmarshaller; 65 | } 66 | 67 | @Override 68 | public boolean supports(Class clazz) { 69 | return marshaller.supports(clazz) && unmarshaller.supports(clazz); 70 | } 71 | 72 | @Override 73 | public void afterPropertiesSet() throws Exception { 74 | List mediaTypes = this.getSupportedMediaTypes(); 75 | Assert.isTrue(mediaTypes.size() > 0, "the " + getClass().getName() + " has no " + 76 | "'supportedMediaTypes.' This is most likely a configuration error" + 77 | " and is not likely to work the way you expect it."); 78 | Assert.notNull(this.marshaller, "the 'thriftMarshaller' can't be null"); 79 | Assert.notNull(this.unmarshaller, "the 'unmarshaller' can't be null"); 80 | } 81 | 82 | @Override 83 | protected Object readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { 84 | InputStream in = inputMessage.getBody(); 85 | try { 86 | return unmarshaller.unmarshal(clazz, in); 87 | } catch (Exception e) { 88 | throw new RuntimeException(e); 89 | } 90 | } 91 | 92 | @Override 93 | protected void writeInternal(Object o, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { 94 | OutputStream out = outputMessage.getBody(); 95 | try { 96 | marshaller.marshal(o, out); 97 | } catch (Exception e) { 98 | throw new RuntimeException(e); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/remoting/thrift/ThriftExporter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 18 | package org.springframework.remoting.thrift; 19 | 20 | import org.apache.thrift.server.TServer; 21 | import org.apache.thrift.server.TThreadPoolServer; 22 | import org.apache.thrift.transport.TServerSocket; 23 | import org.apache.thrift.transport.TServerTransport; 24 | import org.springframework.context.SmartLifecycle; 25 | import org.springframework.obm.thrift.util.ThriftUtil; 26 | import org.springframework.util.Assert; 27 | 28 | import java.net.InetSocketAddress; 29 | 30 | /** 31 | *

Exports Thrift based RPC services. This implementation will expose the Thrift based POJO on the 32 | * {@link #port} specified (or, alternatively, the {@link #address}) 33 | * 34 | * @author Josh Long 35 | * @see org.springframework.remoting.caucho.HessianExporter 36 | */ 37 | public class ThriftExporter extends AbstractThriftExporter implements SmartLifecycle { 38 | 39 | private volatile boolean running = false; 40 | 41 | private TServerTransport transport; 42 | 43 | private TServer tServer; 44 | 45 | private int port = ThriftUtil.DEFAULT_PORT; 46 | 47 | private InetSocketAddress address; 48 | 49 | public void setTransport(TServerTransport transport) { 50 | this.transport = transport; 51 | } 52 | 53 | public void setServer(TServer s) { 54 | this.tServer = s; 55 | } 56 | 57 | public void setPort(int listenPort) { 58 | Assert.isTrue(listenPort > 0, "the port must be a value greater than 0"); 59 | this.port = listenPort; 60 | } 61 | 62 | public void setAddress(InetSocketAddress address) { 63 | Assert.notNull(address, "you have specified a null address"); 64 | this.address = address; 65 | } 66 | 67 | @Override 68 | public boolean isAutoStartup() { 69 | return true; 70 | } 71 | 72 | @Override 73 | public boolean isRunning() { 74 | return running; 75 | } 76 | 77 | @Override 78 | public int getPhase() { 79 | return 0; 80 | } 81 | 82 | @Override 83 | public void start() { 84 | 85 | this.running = true; 86 | try { 87 | 88 | if (logger.isDebugEnabled()) { 89 | logger.debug("starting " + ThriftExporter.class.getName() + ". This exporter's only been tested on Thrift 0.7. Your mileage may vary with other versions"); 90 | } 91 | 92 | TServerTransport serverTransport = this.transport; 93 | if (null == serverTransport) { // ie, no transport specified 94 | if (this.address != null) { 95 | serverTransport = new TServerSocket(this.address); 96 | } else { 97 | serverTransport = new TServerSocket(this.port); 98 | } 99 | } 100 | 101 | TThreadPoolServer.Args args = new TThreadPoolServer.Args(serverTransport); 102 | args.processor(processor); 103 | 104 | if (logger.isDebugEnabled()) { 105 | logger.debug("starting to listen on " + serverTransport.toString()); 106 | } 107 | 108 | if (null == this.tServer) { 109 | tServer = new TThreadPoolServer(args); 110 | } 111 | tServer.serve(); 112 | 113 | } catch (Exception e) { 114 | throw new RuntimeException(e); 115 | } 116 | } 117 | 118 | @Override 119 | public void stop() { 120 | if (null != this.tServer) { 121 | tServer.stop(); 122 | } 123 | this.running = false; 124 | } 125 | 126 | 127 | @Override 128 | public void stop(Runnable callback) { 129 | stop(); 130 | if (callback != null) { 131 | callback.run(); 132 | } 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/obm/messagepack/util/MessagePackUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 18 | package org.springframework.obm.messagepack.util; 19 | 20 | import org.msgpack.MessagePackObject; 21 | import org.springframework.core.GenericCollectionTypeResolver; 22 | 23 | import java.lang.reflect.Field; 24 | import java.lang.reflect.Modifier; 25 | import java.util.*; 26 | import java.util.concurrent.ArrayBlockingQueue; 27 | 28 | /** 29 | * @author Josh Long 30 | */ 31 | @SuppressWarnings("unchecked") 32 | public abstract class MessagePackUtils { 33 | 34 | private static Collection buildReplacementCollection(Collection in) throws Throwable { 35 | 36 | int size = in.size(); 37 | if (in.getClass().isInterface()) { 38 | 39 | if (in.getClass().equals(Set.class)) { 40 | return new HashSet(size); 41 | } 42 | if (in.getClass().equals(List.class)) { 43 | return new ArrayList(size); 44 | } 45 | if (in.getClass().equals(Queue.class)) { 46 | return new ArrayBlockingQueue(size); 47 | } 48 | } else { 49 | return in.getClass().newInstance(); 50 | } 51 | throw new RuntimeException("we couldn't figure out a replacement collection for the input collection type, " + in.getClass().getName()); 52 | } 53 | 54 | private static Object convertMessagePackObject(Object input, Class clzz) { 55 | if (input instanceof MessagePackObject) { 56 | MessagePackObject messagePackObject = (MessagePackObject) input; 57 | return messagePackObject.convert(clzz); 58 | } 59 | return null; 60 | } 61 | 62 | 63 | public static T remapResult(final T result) throws Throwable { 64 | Class clazzOfT = result.getClass(); 65 | 66 | if (ReflectionUtils.isUninterestingClass(clazzOfT)) { 67 | return result; 68 | } 69 | 70 | org.springframework.util.ReflectionUtils.doWithFields(result.getClass(), new org.springframework.util.ReflectionUtils.FieldCallback() { 71 | @Override 72 | public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException { 73 | try { 74 | 75 | if (org.springframework.util.ReflectionUtils.isPublicStaticFinal(field) || Modifier.isFinal(field.getModifiers())) { 76 | return; 77 | } 78 | 79 | if (!field.isAccessible()) { 80 | field.setAccessible(true); 81 | } 82 | 83 | Object value = field.get(result); 84 | 85 | if (Collection.class.isAssignableFrom(value.getClass())) { 86 | 87 | Collection values = (Collection) value; 88 | Collection destination = buildReplacementCollection(values); 89 | Class classOfCollection = GenericCollectionTypeResolver.getCollectionFieldType(field); 90 | for (Object srcObject : values) { 91 | if (srcObject instanceof MessagePackObject) { 92 | destination.add(convertMessagePackObject(srcObject, classOfCollection)); 93 | } else { 94 | destination.add(srcObject); 95 | } 96 | } 97 | // set the new value in place 98 | field.set(result, destination); 99 | } 100 | } catch (Throwable thr) { 101 | throw new RuntimeException(thr); 102 | } 103 | } 104 | }); 105 | 106 | return result; 107 | } 108 | 109 | 110 | } 111 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/obm/avro/support/DecoderFactoryBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.obm.avro.support; 17 | 18 | import org.apache.avro.Schema; 19 | import org.apache.avro.io.BinaryDecoder; 20 | import org.apache.avro.io.Decoder; 21 | import org.apache.avro.io.DecoderFactory; 22 | import org.springframework.util.Assert; 23 | import org.springframework.util.StringUtils; 24 | 25 | import java.io.InputStream; 26 | 27 | 28 | /** 29 | * Convenience class to build a {@link org.apache.avro.io.Decoder} 30 | * 31 | * @author Josh Long 32 | */ 33 | public class DecoderFactoryBuilder { 34 | private final static ThreadLocal decoderThreadLocal = new ThreadLocal(); 35 | 36 | private DecoderFactory decoderFactory = DecoderFactory.get(); 37 | private boolean useBinary = true; 38 | private boolean validate = false; 39 | private boolean useJson = false; 40 | private String input; 41 | private Schema schema; 42 | private InputStream inputStream; 43 | 44 | public DecoderFactoryBuilder setInputStream(InputStream inputStream) { 45 | this.inputStream = inputStream; 46 | return this; 47 | } 48 | 49 | public DecoderFactoryBuilder setInput(String input) { 50 | this.input = input; 51 | return this; 52 | } 53 | 54 | public DecoderFactoryBuilder setSchema(Schema schema) { 55 | this.schema = schema; 56 | return this; 57 | } 58 | 59 | public DecoderFactoryBuilder setUseBinary(boolean useBinary) { 60 | this.useBinary = useBinary; 61 | return this; 62 | } 63 | 64 | public DecoderFactoryBuilder setUseJson(boolean useJson) { 65 | this.useJson = useJson; 66 | return this; 67 | } 68 | 69 | public DecoderFactoryBuilder setValidate(boolean validate) { 70 | this.validate = validate; 71 | return this; 72 | } 73 | 74 | 75 | protected Decoder buildThreadAwareDecoder() throws Exception { 76 | Decoder existingDecoder = decoderThreadLocal.get(); 77 | decoderThreadLocal.set(build(existingDecoder)); 78 | return decoderThreadLocal.get(); 79 | } 80 | 81 | protected Decoder build(Decoder reuse) throws Exception { 82 | 83 | Decoder decoder = null; 84 | if (useBinary) { 85 | Assert.notNull(this.inputStream, "you've selected to use a binary decoder. " + 86 | "Please provide the input stream to decode by " + 87 | "setting the 'inputStream' property"); 88 | decoder = decoderFactory.binaryDecoder(this.inputStream, (BinaryDecoder) reuse); 89 | } else if (useJson) { 90 | Assert.notNull(this.schema, "you've selected to use JSON. Please provide a target schema by setting the 'schema' property"); 91 | Assert.isTrue(StringUtils.hasText(this.input) || this.inputStream != null, "there must be either an inputStream or an inputString to build a JsonDecoder"); 92 | decoder = StringUtils.hasText(this.input) ? 93 | decoderFactory.jsonDecoder(this.schema, this.input) : 94 | decoderFactory.jsonDecoder(this.schema, this.inputStream); 95 | } 96 | 97 | Assert.notNull(decoder, "could not build a decoder. Did you set both 'useJson' and 'userBinary' to false?"); 98 | 99 | if (validate) { 100 | Assert.notNull(this.schema, "you've selected to validate. Please provide a target schema by setting the 'schema' property"); 101 | decoder = decoderFactory.validatingDecoder(this.schema, decoder); 102 | } 103 | return decoder; 104 | } 105 | 106 | public Decoder build() throws Exception { 107 | return buildThreadAwareDecoder(); 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/http/converter/obm/support/BaseMarshallingHttpMessageConverterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.http.converter.obm.support; 17 | 18 | import junit.framework.Assert; 19 | import org.junit.Test; 20 | import org.mockito.Mockito; 21 | import org.springframework.http.HttpHeaders; 22 | import org.springframework.http.HttpInputMessage; 23 | import org.springframework.http.HttpOutputMessage; 24 | import org.springframework.http.MediaType; 25 | import org.springframework.http.converter.obm.MarshallingHttpMessageConverter; 26 | import org.springframework.obm.BaseMarshallerTest; 27 | 28 | import java.io.ByteArrayInputStream; 29 | import java.io.ByteArrayOutputStream; 30 | import java.io.InputStream; 31 | 32 | /** 33 | * Tests the {@link org.springframework.http.converter.obm.MarshallingHttpMessageConverter} 34 | * 35 | * @author Josh Long 36 | */ 37 | public class BaseMarshallingHttpMessageConverterTest extends BaseMarshallerTest { 38 | protected MarshallingHttpMessageConverter marshallingHttpMessageConverter; 39 | 40 | protected MediaType mediaType; 41 | 42 | public void setMediaType(MediaType mediaType) { 43 | this.mediaType = mediaType; 44 | } 45 | 46 | public void setHttpMessageConverter(MarshallingHttpMessageConverter marshallingHttpMessageConverter) { 47 | this.marshallingHttpMessageConverter = marshallingHttpMessageConverter; 48 | } 49 | 50 | private void setup() { 51 | Assert.assertNotNull(this.marshallingHttpMessageConverter); 52 | Assert.assertNotNull(this.marshaller); 53 | Assert.assertNotNull(this.unmarshaller); 54 | Assert.assertNotNull(this.mediaType); 55 | } 56 | 57 | protected void doTestHttpWriting(Class clazz, Object output) throws Throwable { 58 | setup(); 59 | 60 | Assert.assertNotNull("object to output can't be null", output); 61 | 62 | Assert.assertTrue("the thriftMarshaller must be able to read this class ", 63 | marshallingHttpMessageConverter.supports(clazz) && 64 | this.unmarshaller.supports(clazz)); 65 | HttpHeaders headers = Mockito.mock(HttpHeaders.class); 66 | HttpOutputMessage httpOutputMessage = Mockito.mock(HttpOutputMessage.class); 67 | Mockito.when(httpOutputMessage.getHeaders()).thenReturn(headers); 68 | Mockito.when(headers.getContentType()).thenReturn(this.mediaType); 69 | ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 70 | Mockito.when(httpOutputMessage.getBody()).thenReturn(byteArrayOutputStream); 71 | marshallingHttpMessageConverter.write(output, this.mediaType, httpOutputMessage); 72 | byteArrayOutputStream.flush(); 73 | byteArrayOutputStream.close(); 74 | byte[] bytesWritten = byteArrayOutputStream.toByteArray(); 75 | 76 | doTestHttpReading(clazz, output, new ByteArrayInputStream(bytesWritten)); 77 | } 78 | 79 | private void doTestHttpReading(Class clazz, Object output, InputStream inputStream) throws Throwable { 80 | setup(); 81 | Assert.assertNotNull("object to output can't be null", output); 82 | Assert.assertTrue("the thriftMarshaller must be able to read this class ", 83 | marshallingHttpMessageConverter.supports(clazz) && 84 | this.unmarshaller.supports(clazz)); 85 | HttpHeaders headers = Mockito.mock(HttpHeaders.class); 86 | HttpInputMessage inputMessage = Mockito.mock(HttpInputMessage.class); 87 | Mockito.when(headers.getContentType()).thenReturn(this.mediaType); 88 | Mockito.when(inputMessage.getHeaders()).thenReturn(headers); 89 | Mockito.when(inputMessage.getBody()).thenReturn(inputStream); 90 | Object result = marshallingHttpMessageConverter.read(clazz, inputMessage); 91 | Assert.assertNotNull(result); 92 | Assert.assertEquals("the resulting objects must be .equals()", result, output); 93 | } 94 | 95 | @Test 96 | public void doFoo() { 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/remoting/avro/AvroProxyFactoryBean.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.remoting.avro; 17 | 18 | import org.aopalliance.intercept.MethodInterceptor; 19 | import org.aopalliance.intercept.MethodInvocation; 20 | import org.apache.avro.ipc.Transceiver; 21 | import org.apache.avro.ipc.specific.SpecificRequestor; 22 | import org.springframework.aop.framework.ProxyFactory; 23 | import org.springframework.beans.factory.FactoryBean; 24 | import org.springframework.beans.factory.InitializingBean; 25 | import org.springframework.remoting.avro.clients.NettyTransceiverCreationCallback; 26 | import org.springframework.remoting.avro.clients.TransceiverCreationCallback; 27 | import org.springframework.remoting.support.RemoteAccessor; 28 | import org.springframework.util.Assert; 29 | 30 | import java.lang.reflect.Method; 31 | import java.net.InetSocketAddress; 32 | 33 | /** 34 | * {@link org.springframework.beans.factory.FactoryBean} that builds client-side proxies that 35 | * in turn talk to remote Avro RPC implementations 36 | * 37 | * @author Josh Long 38 | * @see org.springframework.remoting.avro.clients.TransceiverCreationCallback 39 | */ 40 | public class AvroProxyFactoryBean extends RemoteAccessor implements InitializingBean, MethodInterceptor, FactoryBean { 41 | 42 | private TransceiverCreationCallback transceiverCreationCallback; 43 | 44 | private int port = 2003; 45 | 46 | private Transceiver transceiver; 47 | private Object serviceProxy; 48 | private InetSocketAddress address; 49 | 50 | private Object client; 51 | 52 | public void setPort(int port) { 53 | this.port = port; 54 | } 55 | 56 | public void setTransceiver(Transceiver transceiver) { 57 | this.transceiver = transceiver; 58 | } 59 | 60 | @Override 61 | public T getObject() throws Exception { 62 | return (T) serviceProxy; 63 | } 64 | 65 | @Override 66 | public Class getObjectType() { 67 | return getServiceInterface(); 68 | } 69 | 70 | @Override 71 | public boolean isSingleton() { 72 | return true; 73 | } 74 | 75 | /** 76 | *

Useful if you want to tailor the creation of the {@link Transceiver } that's used to handle the client side networking.

77 | *

78 | *

This is not a required field because, by default, the implementation uses {@link NettyTransceiverCreationCallback}

79 | * 80 | * @param transceiverCreationCallback the transceiver creation callback 81 | */ 82 | public void setTransceiverCreationCallback(TransceiverCreationCallback transceiverCreationCallback) { 83 | this.transceiverCreationCallback = transceiverCreationCallback; 84 | } 85 | 86 | @Override 87 | public void afterPropertiesSet() throws Exception { 88 | if (null == this.address) { 89 | Assert.isTrue(this.port > 0, "the port must be greater than 0"); 90 | this.address = new InetSocketAddress(port); 91 | } 92 | if (this.transceiverCreationCallback == null) { 93 | this.transceiverCreationCallback = new NettyTransceiverCreationCallback(); 94 | } 95 | if (this.transceiver == null) { 96 | this.transceiver = transceiverCreationCallback.buildTransceiver(this.address); 97 | } 98 | this.client = SpecificRequestor.getClient(getServiceInterface(), transceiver); 99 | Assert.notNull(client, "we weren't able to build a serviceProxy"); 100 | this.serviceProxy = new ProxyFactory(getServiceInterface(), this).getProxy(getBeanClassLoader()); 101 | } 102 | 103 | @Override 104 | public Object invoke(MethodInvocation invocation) throws Throwable { 105 | // now, unless i miss my mark, the interface of this proxy and the proxy we've created locally are the same, 106 | // so it should be a simple matter to forward the MethodInvocation on to the local serviceProxy 107 | Method method = invocation.getMethod(); 108 | 109 | if (logger.isDebugEnabled()) { 110 | logger.debug("invoking " + invocation.toString() + " on the serviceProxy proxy"); 111 | } 112 | 113 | return method.invoke(this.client, invocation.getArguments()); 114 | } 115 | 116 | 117 | } 118 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/obm/snappy/SnappyMarshaller.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.obm.snappy; 18 | 19 | import org.springframework.obm.Marshaller; 20 | import org.springframework.obm.Unmarshaller; 21 | import org.springframework.obm.support.AbstractMarshaller; 22 | import org.springframework.util.Assert; 23 | import org.springframework.util.FileCopyUtils; 24 | import org.xerial.snappy.Snappy; 25 | 26 | import java.io.ByteArrayInputStream; 27 | import java.io.ByteArrayOutputStream; 28 | import java.io.InputStream; 29 | import java.io.OutputStream; 30 | 31 | /** 32 | *

This marshaller is a wrapping {@link org.springframework.obm.Marshaller}, meant to delegate actual 33 | * serialization duties to another {@link org.springframework.obm.Marshaller}. 34 | *

The Snappy library (http://code.google.com/p/snappy-java) is a compression library from Google that is optimized for speed and modest comppression. 35 | *

While Snappy is a C++ library, C bindings are provided and that C binding is wrappd 36 | * by the Snappy-Java project, which consumes the C bindings through JNI. There are 32 and 64 bit builds packaged with the Snappy library for OSX, Linux, and Windows. 37 | * You should not need to do anything to use this (not even setup LD_PATH or library.path, but you 38 | * should be aware that the native code is there. It has been testd and works correctly in multi-classloader environments like Tomcat 39 | *

40 | * 41 | * @author Josh Long 42 | */ 43 | public class SnappyMarshaller extends AbstractMarshaller { 44 | 45 | private Marshaller marshaller; 46 | private Unmarshaller unmarshaller; 47 | 48 | public SnappyMarshaller(Marshaller marshaller) { 49 | this.marshaller = marshaller; 50 | if (this.marshaller instanceof Unmarshaller) { 51 | this.unmarshaller = (Unmarshaller) this.marshaller; 52 | } 53 | Assert.notNull(this.unmarshaller); 54 | Assert.notNull(this.marshaller); 55 | } 56 | 57 | public SnappyMarshaller(Marshaller marshaller, Unmarshaller unmarshaller) { 58 | this.marshaller = marshaller; 59 | this.unmarshaller = unmarshaller; 60 | Assert.notNull(this.unmarshaller); 61 | Assert.notNull(this.marshaller); 62 | } 63 | 64 | public void setMarshaller(Marshaller marshaller) { 65 | this.marshaller = marshaller; 66 | } 67 | 68 | public void setUnmarshaller(Unmarshaller unmarshaller) { 69 | this.unmarshaller = unmarshaller; 70 | } 71 | 72 | @Override 73 | public boolean supports(Class clazz) { 74 | return marshaller.supports(clazz) && unmarshaller.supports(clazz); 75 | } 76 | 77 | @Override 78 | public void marshal(Object obj, OutputStream os) throws Exception { 79 | ByteArrayOutputStream byteArrayOutputStream = null; 80 | try { 81 | byteArrayOutputStream = new ByteArrayOutputStream(); 82 | marshaller.marshal(obj, byteArrayOutputStream); 83 | byteArrayOutputStream.flush(); 84 | byte[] uncompressed = byteArrayOutputStream.toByteArray(); 85 | byte[] compressed = Snappy.compress(uncompressed); 86 | FileCopyUtils.copy(compressed, os); 87 | } catch (Throwable th) { 88 | if (log.isErrorEnabled()) { 89 | log.error("could not compress the object " + (null == obj ? "" : obj + ""), th); 90 | } 91 | throw new RuntimeException(th); 92 | } finally { 93 | if (null != byteArrayOutputStream) { 94 | byteArrayOutputStream.close(); 95 | } 96 | } 97 | } 98 | 99 | @Override 100 | public Object unmarshal(Class clazz, InputStream source) throws Exception { 101 | ByteArrayInputStream byteArrayInputStream = null; 102 | try { 103 | byte[] bytes = FileCopyUtils.copyToByteArray(source); 104 | byte[] ogBytes = Snappy.uncompress(bytes); 105 | byteArrayInputStream = new ByteArrayInputStream(ogBytes); 106 | return unmarshaller.unmarshal(clazz, byteArrayInputStream); 107 | } finally { 108 | if (byteArrayInputStream != null) { 109 | byteArrayInputStream.close(); 110 | } 111 | } 112 | 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/http/converter/obm/MessagePackHttpMessageConverterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.http.converter.obm; 18 | 19 | import org.apache.commons.lang.builder.ToStringBuilder; 20 | import org.apache.commons.logging.Log; 21 | import org.apache.commons.logging.LogFactory; 22 | import org.junit.Assert; 23 | import org.junit.Before; 24 | import org.junit.Test; 25 | import org.mortbay.jetty.Server; 26 | import org.springframework.context.annotation.Bean; 27 | import org.springframework.context.annotation.Configuration; 28 | import org.springframework.http.MediaType; 29 | import org.springframework.http.converter.obm.support.BaseMarshallingHttpMessageConverterTest; 30 | import org.springframework.obm.Marshaller; 31 | import org.springframework.obm.messagepack.Cat; 32 | import org.springframework.obm.messagepack.MessagePackMarshaller; 33 | import org.springframework.stereotype.Controller; 34 | import org.springframework.util.http.RestIntegrationTestUtils; 35 | import org.springframework.web.bind.annotation.PathVariable; 36 | import org.springframework.web.bind.annotation.RequestMapping; 37 | import org.springframework.web.bind.annotation.RequestMethod; 38 | import org.springframework.web.bind.annotation.ResponseBody; 39 | import org.springframework.web.client.RestTemplate; 40 | import org.springframework.web.servlet.config.annotation.EnableWebMvc; 41 | 42 | import java.util.HashMap; 43 | import java.util.Map; 44 | 45 | /** 46 | * @author Josh Long 47 | */ 48 | public class MessagePackHttpMessageConverterTest extends BaseMarshallingHttpMessageConverterTest { 49 | 50 | static MediaType MEDIA_TYPE = new MediaType("application", "x-msgpack"); 51 | private Log log = LogFactory.getLog(getClass()); 52 | private Cat cat = new Cat(); 53 | 54 | @Before 55 | public void before() throws Throwable { 56 | cat.setId(4); 57 | cat.setName("Felix"); 58 | 59 | MessagePackMarshaller marshaller = new MessagePackMarshaller(); 60 | marshaller.afterPropertiesSet(); 61 | 62 | setMarshaller(marshaller); 63 | setUnmarshaller(marshaller); 64 | setMediaType(MEDIA_TYPE); 65 | MarshallingHttpMessageConverter converter = new MarshallingHttpMessageConverter(marshaller); 66 | setHttpMessageConverter(converter); 67 | } 68 | 69 | @Test 70 | public void testHttpReading() throws Throwable { 71 | doTestHttpWriting(cat.getClass(), cat); 72 | } 73 | 74 | 75 | @Test 76 | public void testSimpleIntegration() throws Throwable { 77 | RestIntegrationTestUtils.startServiceAndConnect(MyService.class, new RestIntegrationTestUtils.ServerExecutionCallback() { 78 | @Override 79 | public void doWithServer(RestTemplate clientRestTemplate, Server server) throws Throwable { 80 | 81 | Assert.assertNotNull(clientRestTemplate); 82 | 83 | int id = 344; 84 | Map mapOfVars = new HashMap(); 85 | mapOfVars.put("cat", id); 86 | 87 | Cat customer = clientRestTemplate.getForEntity("http://localhost:8080/ws/cats/{cat}", Cat.class, mapOfVars).getBody(); 88 | Assert.assertTrue(customer.getId() == id); 89 | Assert.assertNotNull(customer.getName()); 90 | 91 | if (log.isDebugEnabled()) { 92 | log.debug("response payload: " + ToStringBuilder.reflectionToString(customer)); 93 | } 94 | 95 | } 96 | }); 97 | 98 | } 99 | 100 | @Configuration 101 | @EnableWebMvc 102 | static public class MyService extends RestIntegrationTestUtils.AbstractRestServiceConfiguration { 103 | @Bean 104 | public CatController controller() { 105 | return new CatController(); 106 | } 107 | 108 | @Override 109 | public Marshaller getMarshaller() { 110 | return new MessagePackMarshaller(); 111 | } 112 | 113 | @Override 114 | public MediaType getMediaType() { 115 | return MEDIA_TYPE; 116 | } 117 | } 118 | 119 | 120 | @Controller 121 | @RequestMapping(value = "/ws/") 122 | public static class CatController { 123 | @RequestMapping(value = "/cats/{id}", method = RequestMethod.GET) 124 | @ResponseBody 125 | public Cat customer(@PathVariable("id") int id) { 126 | return new Cat(Math.random() > .5 ? "Felix" : "Garfield", id); 127 | } 128 | } 129 | } 130 | 131 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/obm/avro/AvroMarshaller.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.obm.avro; 18 | 19 | 20 | import org.apache.avro.Schema; 21 | import org.apache.avro.generic.GenericDatumReader; 22 | import org.apache.avro.generic.GenericDatumWriter; 23 | import org.apache.avro.io.Decoder; 24 | import org.apache.avro.io.Encoder; 25 | import org.springframework.obm.avro.support.DecoderFactoryBuilder; 26 | import org.springframework.obm.avro.support.EncoderFactoryBuilder; 27 | import org.springframework.obm.avro.support.SchemaFactoryBean; 28 | import org.springframework.obm.support.AbstractMarshaller; 29 | import org.springframework.oxm.XmlMappingException; 30 | import org.springframework.util.Assert; 31 | 32 | import java.io.IOException; 33 | import java.io.InputStream; 34 | import java.io.OutputStream; 35 | 36 | /** 37 | * Implementation of the {@link org.springframework.obm.Marshaller} and 38 | * {@link org.springframework.obm.Unmarshaller} interfaces for Avro 39 | * 40 | * @param 41 | * @author Josh Long 42 | */ 43 | public class AvroMarshaller extends AbstractMarshaller { 44 | 45 | private boolean validate = false; 46 | 47 | /** 48 | * dictates whether the {@link org.apache.avro.io.Encoder encoders} and {@link org.apache.avro.io.Decoder decoders} will 49 | * be wrapped in a {@link org.apache.avro.io.ValidatingDecoder} or {@link org.apache.avro.io.ValidatingEncoder} 50 | * 51 | * @param validate whether or not to validate 52 | */ 53 | public void setValidate(boolean validate) { 54 | this.validate = validate; 55 | } 56 | 57 | @Override 58 | public boolean supports(Class clazz) { 59 | try { 60 | Assert.notNull(clazz, "the class must not be null"); 61 | Schema s = new SchemaFactoryBean(clazz).getObject(); 62 | boolean supports = s != null; 63 | 64 | if (log.isDebugEnabled()) { 65 | log.debug("returning " + supports + " for class " + clazz.getName()); 66 | } 67 | 68 | return supports; 69 | } catch (Exception e) { 70 | if (log.isDebugEnabled()) { 71 | log.debug("exception when trying to test whether the class " + clazz.getName() + " has an Avro schema"); 72 | } 73 | return false; 74 | } 75 | } 76 | 77 | @Override 78 | public void marshal(Object obj, OutputStream os) throws IOException, XmlMappingException { 79 | try { 80 | Assert.notNull(obj, "the object to encode must not be null"); 81 | Schema schema = new SchemaFactoryBean(obj.getClass()).getObject(); 82 | Assert.notNull(schema, "the schema must not be null"); 83 | GenericDatumWriter writer = new GenericDatumWriter(schema); 84 | Encoder encoder = new EncoderFactoryBuilder() 85 | .setOutputStream(os) 86 | .setSchema(schema) 87 | .setUseBinary(true) 88 | .setValidate(this.validate) 89 | .build(); 90 | writer.write(obj, encoder); 91 | encoder.flush(); 92 | } catch (Exception e) { 93 | if (log.isDebugEnabled()) { 94 | log.debug("exception when trying to test whether the class " + obj.getClass().getName() + " has an Avro schema"); 95 | } 96 | throw new RuntimeException(e); 97 | } 98 | } 99 | 100 | @Override 101 | public T unmarshal(Class clazz, InputStream source) throws IOException, XmlMappingException { 102 | try { 103 | Assert.notNull(clazz, "the class must not be null"); 104 | Schema schema = new SchemaFactoryBean(clazz).getObject(); 105 | Assert.notNull(schema, "the schema must not be null"); 106 | GenericDatumReader reader = new GenericDatumReader(schema); 107 | Object old = clazz.newInstance(); 108 | Decoder decoder = new DecoderFactoryBuilder() 109 | .setInputStream(source) 110 | .setUseBinary(true) 111 | .setSchema(schema) 112 | .setValidate(this.validate) 113 | .build(); 114 | return (T) reader.read(old, decoder); 115 | } catch (Exception e) { 116 | if (log.isDebugEnabled()) { 117 | log.debug("exception when trying to test whether the class " + clazz.getName() + " has an Avro schema"); 118 | } 119 | throw new RuntimeException(e); 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/jms/support/converter/obm/TestJmsMessageConverter.java: -------------------------------------------------------------------------------- 1 | package org.springframework.jms.support.converter.obm; 2 | 3 | import org.apache.activemq.broker.BrokerService; 4 | import org.junit.Assert; 5 | import org.junit.Before; 6 | import org.junit.Test; 7 | import org.springframework.jms.core.JmsTemplate; 8 | import org.springframework.obm.avro.AvroMarshaller; 9 | import org.springframework.obm.avro.crm.Customer; 10 | import org.springframework.obm.messagepack.Cat; 11 | import org.springframework.obm.messagepack.MessagePackMarshaller; 12 | import org.springframework.obm.protocolbuffers.ProtocolBuffersMarshaller; 13 | import org.springframework.obm.protocolbuffers.crm.Crm; 14 | import org.springframework.obm.thrift.ThriftMarshaller; 15 | import org.springframework.util.jms.JmsIntegrationTestUtils; 16 | 17 | /** 18 | * Tests the {@link org.springframework.obm.avro.AvroMarshaller} with JMS (specifically, an embedded ActiveMQ broker). 19 | * 20 | * @author Josh Long 21 | */ 22 | public class TestJmsMessageConverter { 23 | 24 | // thrift 25 | private ThriftMarshaller thriftMarshaller = new ThriftMarshaller(); 26 | private org.springframework.obm.thrift.crm.Customer thriftCustomer = new org.springframework.obm.thrift.crm.Customer("John", "Doe", "email@email.com", 22); 27 | 28 | // messagepack 29 | private MessagePackMarshaller msgPackMarshaller = new MessagePackMarshaller(); 30 | private Cat msgPackCat; 31 | 32 | // protocol buffers 33 | private ProtocolBuffersMarshaller buffersMarshaller = new ProtocolBuffersMarshaller(); 34 | private Crm.Customer buffersCustomer; 35 | 36 | // avro 37 | private AvroMarshaller avroMarshaller = new AvroMarshaller(); 38 | private Customer avroCustomer = new Customer(); 39 | 40 | @Before 41 | public void before() throws Throwable { 42 | // protocol buffers 43 | buffersCustomer = Crm.Customer.newBuilder().setEmail("email@e.com").setFirstName("john").setLastName("long").build(); 44 | 45 | // avro 46 | avroCustomer.firstName = "josh"; 47 | avroCustomer.lastName = "long"; 48 | avroCustomer.email = "em@em.com"; 49 | avroCustomer.id = (int) (1000 * Math.random()); 50 | 51 | // message pack 52 | msgPackCat = new Cat("Felix", (int) (1000 * Math.random())); 53 | this.msgPackMarshaller.afterPropertiesSet(); 54 | 55 | // thrift 56 | thriftMarshaller.afterPropertiesSet(); 57 | } 58 | 59 | @Test 60 | public void testThrift() throws Throwable { 61 | JmsIntegrationTestUtils.startAndConnectToJmsBroker(org.springframework.obm.thrift.crm.Customer.class, thriftMarshaller, new JmsIntegrationTestUtils.JmsBrokerExecutionCallback() { 62 | @Override 63 | public void doWithActiveMq(BrokerService brokerService, JmsTemplate jmsTemplate) throws Throwable { 64 | String avroDestination = "thrift"; 65 | jmsTemplate.convertAndSend(avroDestination, thriftCustomer); 66 | 67 | org.springframework.obm.thrift.crm.Customer customerReceived = 68 | (org.springframework.obm.thrift.crm.Customer) jmsTemplate.receiveAndConvert(avroDestination); 69 | Assert.assertEquals(thriftCustomer, customerReceived); 70 | } 71 | }); 72 | } 73 | 74 | @Test 75 | public void testAvro() throws Throwable { 76 | JmsIntegrationTestUtils.startAndConnectToJmsBroker(Customer.class, avroMarshaller, new JmsIntegrationTestUtils.JmsBrokerExecutionCallback() { 77 | @Override 78 | public void doWithActiveMq(BrokerService brokerService, JmsTemplate jmsTemplate) throws Throwable { 79 | String avroDestination = "avro"; 80 | jmsTemplate.convertAndSend(avroDestination, avroCustomer); 81 | 82 | Customer customerReceived = (Customer) jmsTemplate.receiveAndConvert(avroDestination); 83 | Assert.assertEquals(avroCustomer, customerReceived); 84 | } 85 | }); 86 | } 87 | 88 | @Test 89 | public void testMessagePack() throws Throwable { 90 | JmsIntegrationTestUtils.startAndConnectToJmsBroker(Cat.class, this.msgPackMarshaller, new JmsIntegrationTestUtils.JmsBrokerExecutionCallback() { 91 | @Override 92 | public void doWithActiveMq(BrokerService brokerService, JmsTemplate jmsTemplate) throws Throwable { 93 | String pbDestination = "messagepack"; 94 | jmsTemplate.convertAndSend(pbDestination, msgPackCat); 95 | Cat rCat = (Cat) jmsTemplate.receiveAndConvert(pbDestination); 96 | Assert.assertEquals(rCat, msgPackCat); 97 | } 98 | }); 99 | } 100 | 101 | @Test 102 | public void testProtocolBuffers() throws Throwable { 103 | JmsIntegrationTestUtils.startAndConnectToJmsBroker(Crm.Customer.class, this.buffersMarshaller, new JmsIntegrationTestUtils.JmsBrokerExecutionCallback() { 104 | @Override 105 | public void doWithActiveMq(BrokerService brokerService, JmsTemplate jmsTemplate) throws Throwable { 106 | String pbDestination = "pb"; 107 | jmsTemplate.convertAndSend(pbDestination, buffersCustomer); 108 | Crm.Customer receivedCustomer = (Crm.Customer) jmsTemplate.receiveAndConvert(pbDestination); 109 | Assert.assertEquals(receivedCustomer, buffersCustomer); 110 | } 111 | }); 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/http/converter/obm/ThriftHttpMessageConverterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.http.converter.obm; 18 | 19 | import org.apache.commons.lang.builder.ToStringBuilder; 20 | import org.apache.commons.logging.Log; 21 | import org.apache.commons.logging.LogFactory; 22 | import org.junit.Assert; 23 | import org.junit.Before; 24 | import org.junit.Test; 25 | import org.mortbay.jetty.Server; 26 | import org.springframework.context.annotation.Bean; 27 | import org.springframework.context.annotation.Configuration; 28 | import org.springframework.http.MediaType; 29 | import org.springframework.http.converter.obm.support.BaseMarshallingHttpMessageConverterTest; 30 | import org.springframework.obm.Marshaller; 31 | import org.springframework.obm.thrift.ThriftCrmService; 32 | import org.springframework.obm.thrift.ThriftMarshaller; 33 | import org.springframework.obm.thrift.crm.Customer; 34 | import org.springframework.stereotype.Controller; 35 | import org.springframework.util.http.RestIntegrationTestUtils; 36 | import org.springframework.web.bind.annotation.PathVariable; 37 | import org.springframework.web.bind.annotation.RequestMapping; 38 | import org.springframework.web.bind.annotation.RequestMethod; 39 | import org.springframework.web.bind.annotation.ResponseBody; 40 | import org.springframework.web.client.RestTemplate; 41 | import org.springframework.web.servlet.config.annotation.EnableWebMvc; 42 | 43 | import javax.inject.Inject; 44 | import java.util.Arrays; 45 | import java.util.HashMap; 46 | import java.util.Map; 47 | 48 | /** 49 | * @author Josh Long 50 | */ 51 | public class ThriftHttpMessageConverterTest extends BaseMarshallingHttpMessageConverterTest { 52 | 53 | private Log log = LogFactory.getLog(getClass()); 54 | 55 | private Customer customer = new Customer("Josh", "Long", "josh@email.com", 242); 56 | 57 | static final public MediaType MEDIA_TYPE = new MediaType("application", "x-thrift"); 58 | 59 | @Before 60 | public void before() throws Throwable { 61 | ThriftMarshaller marshaller = new ThriftMarshaller(); 62 | marshaller.afterPropertiesSet(); 63 | setMarshaller(marshaller); 64 | setUnmarshaller(marshaller); 65 | setMediaType(MEDIA_TYPE); 66 | MarshallingHttpMessageConverter converter = new MarshallingHttpMessageConverter(marshaller); 67 | converter.setSupportedMediaTypes(Arrays.asList(MEDIA_TYPE)); 68 | setHttpMessageConverter(converter); 69 | } 70 | 71 | @Test 72 | public void testHttpReading() throws Throwable { 73 | doTestHttpWriting(customer.getClass(), customer); 74 | } 75 | 76 | @Test 77 | public void testSimpleIntegration() throws Throwable { 78 | RestIntegrationTestUtils.startServiceAndConnect(MyService.class, new RestIntegrationTestUtils.ServerExecutionCallback() { 79 | @Override 80 | public void doWithServer(RestTemplate clientRestTemplate, Server server) throws Throwable { 81 | 82 | Assert.assertNotNull(clientRestTemplate); 83 | 84 | Map mapOfVars = new HashMap(); 85 | mapOfVars.put("customerId", 3); 86 | 87 | Customer customer = clientRestTemplate.getForEntity("http://localhost:8080/ws/customers/{customerId}", Customer.class, mapOfVars).getBody(); 88 | Assert.assertNotNull(customer.getFirstName()); 89 | Assert.assertNotNull(customer.getLastName()); 90 | Assert.assertNotNull(customer.getEmail()); 91 | 92 | if (log.isDebugEnabled()) { 93 | log.debug("response payload: " + ToStringBuilder.reflectionToString(customer)); 94 | } 95 | } 96 | }); 97 | } 98 | 99 | @Configuration 100 | @EnableWebMvc 101 | static public class MyService extends RestIntegrationTestUtils.AbstractRestServiceConfiguration { 102 | @Bean 103 | public CrmRestController controller() { 104 | return new CrmRestController(); 105 | } 106 | 107 | @Bean 108 | public ThriftCrmService crmService() { 109 | return new ThriftCrmService(); 110 | } 111 | 112 | @Override 113 | public Marshaller getMarshaller() { 114 | return new ThriftMarshaller(); 115 | } 116 | 117 | @Override 118 | public MediaType getMediaType() { 119 | return MEDIA_TYPE; 120 | } 121 | } 122 | 123 | 124 | @Controller 125 | @RequestMapping(value = "/ws/") 126 | public static class CrmRestController { 127 | 128 | @Inject private ThriftCrmService crmService; 129 | 130 | @RequestMapping(value = "/customers/{id}", method = RequestMethod.GET) 131 | @ResponseBody 132 | public Customer customer(@PathVariable("id") int id) { 133 | return crmService.getCustomerById(id); 134 | } 135 | } 136 | } 137 | 138 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/remoting/thrift/TestThriftExporter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.remoting.thrift; 18 | 19 | 20 | import org.apache.commons.logging.Log; 21 | import org.apache.commons.logging.LogFactory; 22 | import org.apache.thrift.TException; 23 | import org.junit.After; 24 | import org.junit.Assert; 25 | import org.junit.Before; 26 | import org.junit.Test; 27 | import org.springframework.obm.thrift.crm.Crm; 28 | import org.springframework.obm.thrift.crm.Customer; 29 | import org.springframework.util.ClassUtils; 30 | 31 | import java.util.Arrays; 32 | import java.util.List; 33 | import java.util.Random; 34 | import java.util.concurrent.ExecutorService; 35 | import java.util.concurrent.Executors; 36 | 37 | /** 38 | * a strange, but working, test case that launches the thrift service in a background thread and then shuts it down afterwards which lets us 39 | * verify that we can talk to the exporter service with no problems. 40 | * 41 | * @author Josh Long 42 | */ 43 | public class TestThriftExporter { 44 | 45 | private Log log = LogFactory.getLog(getClass()); 46 | private ExecutorService executor = Executors.newSingleThreadExecutor(); 47 | private ThriftExporter server = new ThriftExporter(); 48 | 49 | private Crm.Iface client; 50 | 51 | private static class ServerRunnable implements Runnable { 52 | 53 | private ThriftExporter exporter; 54 | 55 | public ServerRunnable(ThriftExporter exporter) { 56 | this.exporter = exporter; 57 | } 58 | 59 | @Override 60 | public void run() { 61 | try { 62 | exporter.start(); 63 | } catch (Exception e) { 64 | throw new RuntimeException(e); 65 | } 66 | } 67 | } 68 | 69 | @Test 70 | public void testConsumingFromTheService() throws Throwable { 71 | 72 | Assert.assertNotNull(client); 73 | 74 | String fn = "Josh", ln = "Long", email = "josh@email.com"; 75 | 76 | Customer customer = client.createCustomer(fn, ln, email); 77 | 78 | Assert.assertNotNull(customer); 79 | Assert.assertEquals(customer.getFirstName(), fn); 80 | Assert.assertEquals(customer.getLastName(), ln); 81 | Assert.assertEquals(customer.getEmail(), email); 82 | } 83 | 84 | @Before 85 | public void startServer() throws Exception { 86 | 87 | CustomCrmService crmService = new CustomCrmService(); 88 | 89 | // create the server 90 | ThriftExporter e = new ThriftExporter(); 91 | e.setService(crmService); 92 | e.setServiceInterface(Crm.class); 93 | e.setBeanClassLoader(ClassUtils.getDefaultClassLoader()); 94 | e.afterPropertiesSet(); 95 | server = e; 96 | executor.submit(new ServerRunnable(e)); 97 | 98 | // give the server a bit to bind to the socket and so on... 99 | Thread.sleep(1000 * 1); 100 | 101 | // create the client 102 | ThriftProxyFactoryBean client = new ThriftProxyFactoryBean(); 103 | client.setBeanClassLoader(ClassUtils.getDefaultClassLoader()); 104 | client.setServiceInterface(Crm.Iface.class); 105 | client.afterPropertiesSet(); 106 | this.client = client.getObject(); 107 | 108 | } 109 | 110 | @After 111 | public void stopServer() throws Throwable { 112 | server.stop(new Runnable() { 113 | @Override 114 | public void run() { 115 | if (log.isDebugEnabled()) { 116 | log.debug("stopping the service exporter..."); 117 | } 118 | } 119 | }); 120 | } 121 | 122 | static public class CustomCrmService implements Crm.Iface { 123 | 124 | private List firstNames = Arrays.asList("Josh", "Oliver", "Costin", "Juergen", "Rod", "Mark", "Dave", "Arjen", "Keith", "Adam", "Mike", "Mario"); 125 | private List lastNames = Arrays.asList("Lee", "Loo", "Wi", "Li", "Humble", "Duong", "Kuo"); 126 | private final Random lnRandom = new Random(); 127 | private final Random fnRandom = new Random(); 128 | private final Random idRandom = new Random(); 129 | 130 | private String lastName() { 131 | int i = lnRandom.nextInt(lastNames.size()); 132 | return lastNames.get(i); 133 | } 134 | 135 | private String firstName() { 136 | int i = fnRandom.nextInt(firstNames.size()); 137 | return firstNames.get(i); 138 | } 139 | 140 | @Override 141 | public Customer createCustomer(String fn, String ln, String email) throws TException { 142 | return new Customer(fn, ln, email, idRandom.nextInt()); 143 | } 144 | 145 | @Override 146 | public Customer getCustomerById(int customerId) throws TException { 147 | String fn = firstName(); 148 | String ln = lastName(); 149 | return new Customer(fn, ln, fn + "@email.com", customerId); 150 | } 151 | } 152 | 153 | } 154 | -------------------------------------------------------------------------------- /obm/src/test/java/org/springframework/http/converter/obm/AvroHttpMessageConverterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.http.converter.obm; 17 | 18 | import org.apache.commons.lang.builder.ToStringBuilder; 19 | import org.apache.commons.logging.Log; 20 | import org.apache.commons.logging.LogFactory; 21 | import org.junit.Assert; 22 | import org.junit.Before; 23 | import org.junit.Test; 24 | import org.mortbay.jetty.Server; 25 | import org.springframework.context.annotation.Bean; 26 | import org.springframework.context.annotation.Configuration; 27 | import org.springframework.http.MediaType; 28 | import org.springframework.http.converter.obm.support.BaseMarshallingHttpMessageConverterTest; 29 | import org.springframework.obm.Marshaller; 30 | import org.springframework.obm.avro.AvroMarshaller; 31 | import org.springframework.obm.avro.crm.Customer; 32 | import org.springframework.stereotype.Controller; 33 | import org.springframework.util.http.RestIntegrationTestUtils; 34 | import org.springframework.web.bind.annotation.PathVariable; 35 | import org.springframework.web.bind.annotation.RequestMapping; 36 | import org.springframework.web.bind.annotation.RequestMethod; 37 | import org.springframework.web.bind.annotation.ResponseBody; 38 | import org.springframework.web.client.RestTemplate; 39 | import org.springframework.web.servlet.config.annotation.EnableWebMvc; 40 | 41 | import java.util.HashMap; 42 | import java.util.Map; 43 | 44 | /** 45 | * test the {@link org.springframework.http.converter.HttpMessageConverter avro http converter} 46 | * 47 | * @author Josh Long 48 | */ 49 | public class AvroHttpMessageConverterTest extends BaseMarshallingHttpMessageConverterTest { 50 | static MediaType MEDIA_TYPE = new MediaType("avro", "binary"); 51 | 52 | private Log log = LogFactory.getLog(getClass()); 53 | 54 | private Customer customer = new Customer(); 55 | 56 | @Before 57 | public void before() throws Throwable { 58 | customer.id = 225; 59 | customer.firstName = "Josh"; 60 | customer.lastName = "Long"; 61 | customer.email = "josh@emai.com"; 62 | 63 | AvroMarshaller marshaller = new AvroMarshaller(); 64 | 65 | setMarshaller(marshaller); 66 | setUnmarshaller(marshaller); 67 | setMediaType(MEDIA_TYPE); 68 | MarshallingHttpMessageConverter converter = new MarshallingHttpMessageConverter(marshaller); 69 | setHttpMessageConverter(converter); 70 | } 71 | 72 | @Test 73 | public void testAvroMarshaller() throws Throwable { 74 | doTestHttpWriting(customer.getClass(), customer); 75 | } 76 | 77 | static private String fn = "george", ln = "harrison", email = "geore@email.com"; 78 | 79 | @Test 80 | public void testSimpleIntegration() throws Throwable { 81 | RestIntegrationTestUtils.startServiceAndConnect(MyService.class, new RestIntegrationTestUtils.ServerExecutionCallback() { 82 | @Override 83 | public void doWithServer(RestTemplate restTemplate, Server server) throws Throwable { 84 | Assert.assertNotNull(restTemplate); 85 | 86 | int id = 344; 87 | Map mapOfVars = new HashMap(); 88 | mapOfVars.put("cid", id); 89 | 90 | Customer customer = restTemplate.getForEntity("http://localhost:8080/ws/customers/{cid}", Customer.class, mapOfVars).getBody(); 91 | Assert.assertTrue(customer.id == id); 92 | Assert.assertTrue(customer.firstName.toString().equals(fn)); 93 | Assert.assertTrue(customer.lastName.toString().equals(ln)); 94 | Assert.assertTrue(customer.email.toString().equals(email)); 95 | 96 | if (log.isDebugEnabled()) { 97 | log.debug("response payload: " + ToStringBuilder.reflectionToString(customer)); 98 | } 99 | 100 | } 101 | }); 102 | 103 | } 104 | 105 | @Configuration 106 | @EnableWebMvc 107 | static public class MyService extends RestIntegrationTestUtils.AbstractRestServiceConfiguration { 108 | @Bean 109 | public CustomerController controller() { 110 | return new CustomerController(); 111 | } 112 | 113 | @Override 114 | public Marshaller getMarshaller() { 115 | return new AvroMarshaller(); 116 | } 117 | 118 | @Override 119 | public MediaType getMediaType() { 120 | return MEDIA_TYPE; 121 | } 122 | } 123 | 124 | 125 | @Controller 126 | @RequestMapping(value = "/ws/") 127 | public static class CustomerController { 128 | @RequestMapping(value = "/customers/{id}", method = RequestMethod.GET) 129 | @ResponseBody 130 | public Customer customer(@PathVariable("id") int id) { 131 | 132 | Customer avroCustomer = new Customer(); 133 | avroCustomer.id = id; 134 | avroCustomer.firstName = fn; 135 | avroCustomer.lastName = ln; 136 | avroCustomer.email = email; 137 | return avroCustomer; 138 | } 139 | } 140 | 141 | } -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/remoting/thrift/ThriftServiceExporter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.remoting.thrift; 18 | 19 | import org.apache.thrift.TException; 20 | import org.apache.thrift.protocol.TBinaryProtocol; 21 | import org.apache.thrift.protocol.TProtocol; 22 | import org.apache.thrift.protocol.TProtocolFactory; 23 | import org.apache.thrift.transport.TIOStreamTransport; 24 | import org.apache.thrift.transport.TTransport; 25 | import org.springframework.beans.factory.InitializingBean; 26 | import org.springframework.http.MediaType; 27 | import org.springframework.util.Assert; 28 | import org.springframework.web.HttpRequestHandler; 29 | 30 | import javax.servlet.ServletException; 31 | import javax.servlet.http.HttpServletRequest; 32 | import javax.servlet.http.HttpServletResponse; 33 | import java.io.IOException; 34 | import java.io.InputStream; 35 | import java.io.OutputStream; 36 | import java.util.ArrayList; 37 | import java.util.Collection; 38 | import java.util.HashMap; 39 | import java.util.Map; 40 | 41 | /** 42 | *

43 | * Simple {@link HttpRequestHandler} implementation that fields an incoming request and 44 | * forwards it to Thrift to handle. The {@link HttpRequestHandler} is the simplest of all 45 | * Spring Web components. 46 | *

47 | *

The easiest way to expose an HttpRequestHandler bean in Spring style 48 | * is to define it in Spring's root web application context and define 49 | * an {@link org.springframework.web.context.support.HttpRequestHandlerServlet} 50 | * in web.xml, pointing at the target HttpRequestHandler bean 51 | * through its servlet-name which needs to match the target bean name.* 52 | *

53 | *

This code is inspired by (and in large part duplicates) the {@link org.apache.thrift.server.TServlet}, but adapted 54 | * to work with Spring web infrastructure, benefiting from dependency injection and more. 55 | *

56 | *

The class provides the ability to register a (static) list of headers that 57 | * to be written on to the response. 58 | *

59 | *

Simple configuration using Java configuration might look like:

60 | *

61 | * 62 | * 63 | * @author Josh Long 64 | * @Bean public ThriftServiceExporter exporter (){ 65 | * MyThriftService.Iface serviceBean = new MyRegularServiceBean(); 66 | * ThriftServiceExporter e = new ThriftServiceExporter (); 67 | * e.setService(serviceBean); 68 | * e.setServiceInterface(MyThriftService.Iface.class); // or, MyThriftService.class 69 | * return e; 70 | * } 71 | * 72 | *

73 | *

Thrift clients will by default 74 | * use the Thrift binary protocol unless the {@link #protocolFactory} is overridden. 75 | * @see org.apache.thrift.server.TServlet 76 | * @see HttpRequestHandler 77 | * @see org.springframework.remoting.caucho.HessianServiceExporter 78 | */ 79 | public class ThriftServiceExporter extends AbstractThriftExporter implements InitializingBean, HttpRequestHandler { 80 | 81 | private TProtocolFactory protocolFactory = new TBinaryProtocol.Factory(); 82 | 83 | private final Collection> customHeaders = new ArrayList>(); 84 | 85 | private MediaType mediaType; 86 | 87 | public void setProtocolFactory(TProtocolFactory inProtocolFactory) { 88 | this.protocolFactory = inProtocolFactory; 89 | } 90 | 91 | public void setMediaType(MediaType mediaType) { 92 | this.mediaType = mediaType; 93 | } 94 | 95 | public void addCustomHeader(String k, String v) { 96 | Map header = new HashMap(); 97 | header.put(k, v); 98 | this.customHeaders.add(header.entrySet().iterator().next()); 99 | } 100 | 101 | public void setCustomHeaders(Collection> headers) { 102 | this.customHeaders.clear(); 103 | this.customHeaders.addAll(headers); 104 | } 105 | 106 | @Override 107 | public void afterPropertiesSet() throws Exception { 108 | super.afterPropertiesSet(); 109 | Assert.notNull(this.protocolFactory, "the 'protocolFactory' can't be null"); 110 | } 111 | 112 | @Override 113 | public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 114 | try { 115 | 116 | if (null != mediaType) { 117 | response.setContentType(mediaType.toString()); 118 | } 119 | 120 | if (null != this.customHeaders) { 121 | for (Map.Entry header : this.customHeaders) { 122 | response.addHeader(header.getKey(), header.getValue()); 123 | } 124 | } 125 | InputStream in = request.getInputStream(); 126 | OutputStream out = response.getOutputStream(); 127 | 128 | // this is not pluggable from this end 129 | TTransport transport = new TIOStreamTransport(in, out); 130 | TProtocol protocol = protocolFactory.getProtocol(transport); 131 | processor.process(protocol, protocol); 132 | out.flush(); 133 | } catch (TException te) { 134 | throw new ServletException(te); 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/remoting/thrift/ThriftProxyFactoryBean.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.remoting.thrift; 18 | 19 | import org.aopalliance.intercept.MethodInterceptor; 20 | import org.aopalliance.intercept.MethodInvocation; 21 | import org.apache.thrift.protocol.TBinaryProtocol; 22 | import org.apache.thrift.protocol.TProtocol; 23 | import org.apache.thrift.protocol.TProtocolFactory; 24 | import org.apache.thrift.transport.TSocket; 25 | import org.apache.thrift.transport.TTransport; 26 | import org.springframework.aop.framework.ProxyFactory; 27 | import org.springframework.beans.factory.FactoryBean; 28 | import org.springframework.beans.factory.InitializingBean; 29 | import org.springframework.obm.thrift.util.ThriftUtil; 30 | import org.springframework.remoting.support.RemoteAccessor; 31 | import org.springframework.util.Assert; 32 | import org.springframework.util.ClassUtils; 33 | 34 | import java.lang.reflect.Constructor; 35 | import java.lang.reflect.Method; 36 | 37 | /** 38 | * Builds proxies that can connect to a Thrift RPC service. 39 | *

40 | *

Thrift clients will by default 41 | * use the Thrift binary protocol unless the {@link #protocolFactory} is overridden. 42 | * 43 | * @author Josh Long 44 | * @see org.springframework.remoting.caucho.HessianProxyFactoryBean 45 | */ 46 | public class ThriftProxyFactoryBean extends RemoteAccessor implements InitializingBean, MethodInterceptor, FactoryBean { 47 | 48 | // default protocol will be binary 49 | private TProtocolFactory protocolFactory = new TBinaryProtocol.Factory(); 50 | 51 | // transport is optional 52 | private TTransport transport; 53 | 54 | // protocol is optional 55 | private TProtocol protocol; 56 | 57 | // the client as created using the Thrift APIs 58 | private Object client; 59 | 60 | // the proxy that we create which is in turn returned to the client of this class 61 | private Object serviceProxy; 62 | 63 | private String host = "127.0.0.1"; 64 | 65 | private int port = ThriftUtil.DEFAULT_PORT; 66 | 67 | public void setProtocolFactory(TProtocolFactory inProtocolFactory) { 68 | this.protocolFactory = inProtocolFactory; 69 | } 70 | 71 | public void setTransport(TTransport transport) { 72 | this.transport = transport; 73 | } 74 | 75 | public void setProtocol(TProtocol protocol) { 76 | this.protocol = protocol; 77 | } 78 | 79 | public void setPort(int port) { 80 | this.port = port; 81 | } 82 | 83 | public void setHost(String host) { 84 | this.host = host; 85 | } 86 | 87 | @Override 88 | public void setServiceInterface(Class serviceInterface) { 89 | super.setServiceInterface(ThriftUtil.buildServiceInterface(serviceInterface)); 90 | } 91 | 92 | public T getObject() { 93 | return (T) this.serviceProxy; 94 | } 95 | 96 | public Class getObjectType() { 97 | return getServiceInterface(); 98 | } 99 | 100 | public boolean isSingleton() { 101 | return true; 102 | } 103 | 104 | @Override 105 | public Object invoke(MethodInvocation invocation) throws Throwable { 106 | // now, unless i miss my mark, the interface of this proxy and the proxy weve created locally are the same, 107 | // so it should be a simple matter to forward the MethodInvocation on to the local client 108 | Method method = invocation.getMethod(); 109 | 110 | if (logger.isDebugEnabled()) { 111 | logger.debug("invoking " + invocation.toString() + " on the client proxy"); 112 | } 113 | 114 | return method.invoke(this.client, invocation.getArguments()); 115 | } 116 | 117 | @Override 118 | public void afterPropertiesSet() { 119 | if (getServiceInterface() == null) { 120 | throw new IllegalArgumentException("Property 'serviceInterface' is required"); 121 | } 122 | if (this.transport == null) { 123 | Assert.notNull(this.host, "Property 'host' is required"); 124 | Assert.isTrue(this.port > 0, "Property 'port' is required and must be greater than 0"); 125 | this.transport = new TSocket(this.host, this.port); 126 | } 127 | 128 | if (this.protocol == null) { 129 | this.protocol = this.protocolFactory.getProtocol(this.transport); 130 | } 131 | 132 | try { 133 | Class thriftClass = getServiceInterface().getEnclosingClass(); 134 | Assert.notNull(thriftClass, "the enclosing class must not be null"); 135 | 136 | Class clientClass = ThriftUtil.getThriftServiceInnerClassOrNull(thriftClass, "$Client", false); 137 | Assert.notNull(clientClass, "the client class must not be null "); 138 | 139 | Constructor constructor = ClassUtils.getConstructorIfAvailable(clientClass, TProtocol.class); 140 | 141 | this.client = constructor.newInstance(this.protocol); 142 | 143 | Assert.notNull(this.client, "the Thrift RPC client was not correctly created. Aborting."); 144 | this.serviceProxy = new ProxyFactory(getServiceInterface(), this).getProxy(getBeanClassLoader()); 145 | this.transport.open(); 146 | } catch (Exception e) { 147 | throw new RuntimeException(e); 148 | } 149 | } 150 | 151 | 152 | } 153 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/obm/messagepack/util/ReflectionUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.obm.messagepack.util; 18 | 19 | import org.apache.commons.logging.Log; 20 | import org.apache.commons.logging.LogFactory; 21 | import org.msgpack.MessagePack; 22 | 23 | import java.lang.reflect.Method; 24 | import java.util.*; 25 | 26 | /** 27 | * This code crawls the entire object graph, looking for interesting objects that are found on your service interface. It ignores 28 | * obviously incorrect objects like objects from MesssagePack itself (which shouldnt be registered), and objects from the JDK that 29 | * already are registered (like 'int') or shouldn't be (like 'void') 30 | * 31 | * @author Josh Long 32 | */ 33 | public abstract class ReflectionUtils { 34 | 35 | private static Log log = LogFactory.getLog(ReflectionUtils.class); 36 | 37 | 38 | /** 39 | * Callback for the {@link TypeUtils#getGenericTypesForReturnValue(java.lang.reflect.Method)} method. 40 | */ 41 | public static interface ClassTraversalCallback { 42 | void doWithClass(Class o); 43 | } 44 | 45 | /** 46 | * Utility object to help traverse objects to "discover" any related types. 47 | */ 48 | private static class ObjectClassTraverser { 49 | 50 | private Set prefixesToAvoid = new HashSet(); 51 | 52 | private ObjectClassTraverser(Set prefixesToAvoid) { 53 | this.prefixesToAvoid = prefixesToAvoid; 54 | } 55 | 56 | private Collection findClassesToVisit(Method method) { 57 | Set classes = new HashSet(); 58 | classes.add(method.getReturnType()); 59 | Collections.addAll(classes, method.getParameterTypes()); 60 | Collections.addAll(classes, TypeUtils.getGenericTypesForReturnValue(method)); 61 | return classes; 62 | } 63 | 64 | private org.springframework.util.ReflectionUtils.MethodFilter nonObjectMethodsFilter = new org.springframework.util.ReflectionUtils.MethodFilter() { 65 | private List methods = Arrays.asList(Object.class.getDeclaredMethods()); 66 | private String packageForJavaLang = String.class.getPackage().getName(); 67 | 68 | @Override 69 | public boolean matches(Method method) { 70 | 71 | if (log.isDebugEnabled()) { 72 | log.debug(method.toGenericString()); 73 | log.debug("is found? : " + methods.contains(method)); 74 | } 75 | 76 | return !method.getDeclaringClass().getPackage().getName().equalsIgnoreCase(packageForJavaLang) 77 | && !methods.contains(method); 78 | } 79 | }; 80 | 81 | private boolean shouldSkip(Class clzz) { 82 | String className = clzz.getName(); 83 | for (String p : this.prefixesToAvoid) { 84 | if (className.startsWith(p)) { 85 | return true; 86 | } 87 | } 88 | return false; 89 | } 90 | 91 | 92 | protected void doCrawl(Class clzz, final Set toVisit, final ClassTraversalCallback callback) { 93 | org.springframework.util.ReflectionUtils.MethodCallback mc = new org.springframework.util.ReflectionUtils.MethodCallback() { 94 | @Override 95 | public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { 96 | Collection classesToVisit = findClassesToVisit(method); 97 | for (Class c : classesToVisit) { 98 | if (!isUninterestingClass(c) && !shouldSkip(c)) { 99 | if (!toVisit.contains(c)) { 100 | toVisit.add(c); 101 | doCrawl(c, toVisit, callback); 102 | callback.doWithClass(c); 103 | } 104 | } 105 | } 106 | } 107 | }; 108 | org.springframework.util.ReflectionUtils.doWithMethods(clzz, mc, nonObjectMethodsFilter); 109 | } 110 | } 111 | 112 | public static void crawlJavaBeanObjectGraph(Class src, ClassTraversalCallback objectCallback, Set classNamePrefixesToAvoid) { 113 | final Set classesToVisit = new HashSet(); 114 | ObjectClassTraverser classTraverser = new ObjectClassTraverser(classNamePrefixesToAvoid); 115 | classTraverser.doCrawl(src, classesToVisit, objectCallback); 116 | } 117 | 118 | public static void crawlJavaBeanObjectGraph(Class src, ClassTraversalCallback objectCallback) { 119 | crawlJavaBeanObjectGraph(src, objectCallback, new HashSet()); 120 | } 121 | 122 | 123 | /** 124 | * is the class a unique class likely to be worth registering? 125 | * 126 | * @param clazz 127 | * @return 128 | */ 129 | public static boolean isUninterestingClass(Class clazz) { 130 | String javaPackage = "java"; 131 | String messagePackPackage = MessagePack.class.getPackage().getName(); 132 | String clazzName = clazz.getName(); 133 | return !(!clazzName.startsWith(javaPackage) && !clazzName.startsWith(messagePackPackage) && 134 | !clazz.isInterface() && !clazz.isPrimitive() && !clazz.isArray() && 135 | !clazzName.startsWith(MessagePack.class.getPackage().getName())); 136 | } 137 | 138 | } 139 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/remoting/messagepack/MessagePackProxyFactoryBean.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.remoting.messagepack; 18 | 19 | import org.aopalliance.intercept.MethodInterceptor; 20 | import org.aopalliance.intercept.MethodInvocation; 21 | import org.apache.commons.logging.Log; 22 | import org.apache.commons.logging.LogFactory; 23 | import org.msgpack.rpc.Client; 24 | import org.msgpack.rpc.config.ClientConfig; 25 | import org.msgpack.rpc.loop.EventLoop; 26 | import org.springframework.aop.framework.ProxyFactory; 27 | import org.springframework.beans.factory.BeanClassLoaderAware; 28 | import org.springframework.beans.factory.FactoryBean; 29 | import org.springframework.beans.factory.InitializingBean; 30 | import org.springframework.obm.messagepack.support.MessagePackRegistrar; 31 | import org.springframework.obm.messagepack.util.MessagePackUtils; 32 | import org.springframework.remoting.support.RemoteAccessor; 33 | import org.springframework.util.Assert; 34 | 35 | import java.util.HashSet; 36 | import java.util.Set; 37 | 38 | /** 39 | * Used to create client side proxies that can communicate with the remote services. 40 | *

41 | * The interface used on the client does not need to match the interface exposed on the server. 42 | * 43 | * @author Josh Long 44 | * @see org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean 45 | * @see org.springframework.remoting.rmi.RmiProxyFactoryBean 46 | */ 47 | public class MessagePackProxyFactoryBean extends RemoteAccessor implements FactoryBean, BeanClassLoaderAware, InitializingBean { 48 | 49 | private Log log = LogFactory.getLog(getClass()); 50 | private boolean remapResults = true; 51 | 52 | private boolean exportServiceParameters = true; 53 | private Set classes = new HashSet(); 54 | private boolean serializeJavaBeanProperties = true; 55 | 56 | private MessagePackRegistrar registrar = new MessagePackRegistrar(); 57 | 58 | private ClientConfig clientConfig; 59 | 60 | private Client client; 61 | private EventLoop eventLoop; 62 | private T proxy; 63 | private String host = "127.0.0.1"; 64 | private ClassLoader classLoader; 65 | private int port = 1995; 66 | 67 | public void setHost(String host) { 68 | this.host = host; 69 | } 70 | 71 | public void setPort(int port) { 72 | this.port = port; 73 | } 74 | 75 | @Override 76 | public void setBeanClassLoader(ClassLoader classLoader) { 77 | this.classLoader = classLoader; 78 | } 79 | 80 | @Override 81 | public T getObject() throws Exception { 82 | return this.proxy; 83 | } 84 | 85 | @Override 86 | public Class getObjectType() { 87 | return this.proxy.getClass(); 88 | } 89 | 90 | @Override 91 | public boolean isSingleton() { 92 | return false; 93 | } 94 | 95 | /** 96 | * When {@link org.msgpack.MessagePack} sends back the object graph, it comes in as the first level object, 97 | * then any relationships come in as collections of {@link org.msgpack.MessagePackObject}, not the original type. 98 | *

99 | * Well, using some heuristics (specifically, w.r.t. to generics), we can automatically remap these results onto your domain 100 | * POJOs for you, transparently, before you get the results. 101 | */ 102 | private MethodInterceptor objectGraphCleaningMethodInterceptor = new MethodInterceptor() { 103 | @Override 104 | public Object invoke(MethodInvocation invocation) throws Throwable { 105 | if (log.isDebugEnabled()) { 106 | log.debug("the client called: " + invocation.getMethod().toGenericString()); 107 | } 108 | return MessagePackUtils.remapResult(invocation.proceed()); 109 | } 110 | }; 111 | 112 | @SuppressWarnings("unchecked") 113 | @Override 114 | public void afterPropertiesSet() throws Exception { 115 | 116 | registrar.setSerializeJavaBeanProperties(this.serializeJavaBeanProperties); 117 | if (exportServiceParameters) { 118 | registrar.discoverClasses(getServiceInterface()); 119 | } 120 | registrar.registerClasses(this.classes); 121 | registrar.afterPropertiesSet(); 122 | 123 | if (eventLoop == null) { 124 | this.eventLoop = new EventLoopFactoryBean().getObject(); 125 | } 126 | if (clientConfig != null) { 127 | client = new Client(this.host, this.port, this.clientConfig, this.eventLoop); 128 | } else { 129 | client = new Client(this.host, this.port, this.eventLoop); 130 | } 131 | 132 | Assert.notNull(this.client, "the client can't be null"); 133 | Assert.notNull(this.host, "the host can't be null"); 134 | 135 | Object p = client.proxy(getServiceInterface()); 136 | 137 | if (remapResults) { 138 | ProxyFactory factory = new ProxyFactory(p); 139 | factory.addInterface(getServiceInterface()); 140 | factory.addAdvice(objectGraphCleaningMethodInterceptor); 141 | p = (T) factory.getProxy(getBeanClassLoader()); 142 | } 143 | this.proxy = (T) p; 144 | 145 | Assert.notNull(this.proxy, "the proxy can't be null"); 146 | 147 | } 148 | 149 | /** 150 | * Should the results be re-built based on heuristics designed to capture the intent of the code 151 | * 152 | * @param remapResults 153 | */ 154 | public void setRemapResults(boolean remapResults) { 155 | this.remapResults = remapResults; 156 | } 157 | 158 | 159 | public void setExportServiceParameters(boolean exportServiceParameters) { 160 | this.exportServiceParameters = exportServiceParameters; 161 | } 162 | 163 | public void setClientConfig(ClientConfig clientConfig) { 164 | this.clientConfig = clientConfig; 165 | } 166 | 167 | public void setSerializeJavaBeanProperties(boolean serializeJavaBeanProperties) { 168 | this.serializeJavaBeanProperties = serializeJavaBeanProperties; 169 | } 170 | 171 | } 172 | -------------------------------------------------------------------------------- /obm/src/main/java/org/springframework/remoting/jbr/JbossRemotingProxyFactoryBean.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.remoting.jbr; 18 | 19 | import org.aopalliance.intercept.MethodInterceptor; 20 | import org.aopalliance.intercept.MethodInvocation; 21 | import org.jboss.remoting.transporter.TransporterClient; 22 | import org.springframework.aop.framework.ProxyFactory; 23 | import org.springframework.beans.factory.BeanNameAware; 24 | import org.springframework.beans.factory.FactoryBean; 25 | import org.springframework.beans.factory.InitializingBean; 26 | import org.springframework.remoting.support.RemoteAccessor; 27 | import org.springframework.util.Assert; 28 | import org.springframework.util.StringUtils; 29 | 30 | import java.lang.reflect.Method; 31 | 32 | /** 33 | * Supports proxying clients for JBoss Remoting. 34 | *

35 | * There are two different types of serialization 36 | *

37 | * the default, JBoss, uses a special serialization library from JBoss that 38 | *

    39 | *
  • Eschews the need to implement {@link java.io.Serializable}
  • 40 | *
  • Eschews the need to
  • 41 | *
42 | *

43 | * http://www.theserverlabs.com/blog/2009/02/19/jboss-remoting-jboss-serialization-kills-javarmi-and-spring-remoting/ 44 | * 45 | * @author Josh Long 46 | */ 47 | public class JbossRemotingProxyFactoryBean extends RemoteAccessor implements InitializingBean, BeanNameAware, MethodInterceptor, FactoryBean { 48 | 49 | private JbossSerialization serializationType = JbossSerialization.JBOSS; 50 | 51 | private String transport = "socket"; 52 | 53 | private String host = "127.0.0.1"; 54 | 55 | private int port = 5400; 56 | 57 | private Object client; 58 | 59 | private T serviceProxy; 60 | 61 | private String serverName; 62 | 63 | private boolean clustered; 64 | 65 | private String beanName; 66 | 67 | private String url; 68 | 69 | public void setSerializationType(JbossSerialization serializationType) { 70 | this.serializationType = serializationType; 71 | } 72 | 73 | public void setHost(String host) { 74 | this.host = host; 75 | } 76 | 77 | public void setServerName(String serverName) { 78 | this.serverName = serverName; 79 | } 80 | 81 | public void setClustered(boolean clustered) { 82 | this.clustered = clustered; 83 | } 84 | 85 | public void setPort(int port) { 86 | this.port = port; 87 | } 88 | 89 | public void setUrl(String url) { 90 | this.url = url; 91 | } 92 | 93 | public void setTransport(String transport) { 94 | this.transport = transport; 95 | } 96 | 97 | @Override 98 | public void setBeanName(String name) { 99 | this.beanName = name; 100 | } 101 | 102 | @Override 103 | @SuppressWarnings("unchecked") 104 | public void afterPropertiesSet() throws Exception { 105 | if (!StringUtils.hasText(this.serverName)) { 106 | this.serverName = this.beanName; 107 | } 108 | 109 | if (!StringUtils.hasText(this.url)) { 110 | this.url = buildUrl(); 111 | } 112 | 113 | if (logger.isDebugEnabled()) { 114 | logger.debug(getServiceInterface() + " client URL is " + this.url); 115 | } 116 | 117 | Class clientInterface = getServiceInterface(); 118 | 119 | // build the jbr client 120 | this.client = (T) TransporterClient.createTransporterClient(this.url, clientInterface); 121 | Assert.isInstanceOf(getServiceInterface(), this.client); 122 | 123 | // build the object that'll manage calls from the client to that jbr proxy 124 | serviceProxy = (T) new ProxyFactory(clientInterface, this).getProxy(getBeanClassLoader()); 125 | 126 | } 127 | 128 | 129 | protected String buildUrl() { 130 | Assert.hasText(this.transport); 131 | Assert.hasText(this.host); 132 | Assert.notNull(this.serializationType, "you must specify a serialization type (" + 133 | JbossSerialization.JBOSS.name() + "," + 134 | JbossSerialization.JAVA.name() + ")"); 135 | Assert.isTrue(this.port > 0, "you must specify a non-zero port"); 136 | return transport + "://" + host + ":" + port + "/?serializationtype=" + serializationType.name().toLowerCase(); 137 | } 138 | 139 | 140 | @Override 141 | public T getObject() throws Exception { 142 | return serviceProxy; 143 | } 144 | 145 | @Override 146 | public Class getObjectType() { 147 | return getServiceInterface(); 148 | } 149 | 150 | @Override 151 | public boolean isSingleton() { 152 | return true; 153 | } 154 | 155 | @Override 156 | public Object invoke(MethodInvocation invocation) throws Throwable { 157 | // now, unless i miss my mark, the interface of this proxy and the proxy we've created locally are the same, 158 | // so it should be a simple matter to forward the MethodInvocation on to the local client 159 | Method method = invocation.getMethod(); 160 | 161 | if (method.getName().equals("toString")) { 162 | return "proxy for " + getServiceInterface(); 163 | } 164 | 165 | if (logger.isDebugEnabled()) { 166 | logger.debug("invoking " + invocation.toString() + " on the client proxy"); 167 | } 168 | 169 | // find the same method on the client 170 | if (logger.isDebugEnabled()) { 171 | for (Method m : client.getClass().getMethods()) { 172 | logger.debug("discovered " + m.toGenericString() + " on the client proxy."); 173 | } 174 | } 175 | 176 | 177 | Assert.isInstanceOf(getServiceInterface(), this.client); 178 | Method clientMethodSpecifically = this.client.getClass().getMethod(method.getName(), invocation.getMethod().getParameterTypes()); 179 | Assert.notNull(clientMethodSpecifically); 180 | return clientMethodSpecifically.invoke(this.client, invocation.getArguments()); 181 | } 182 | } 183 | --------------------------------------------------------------------------------