Использование Spring Remoting
Q: В Spring есть возможность работать с Remoting. Собственно нужен самый простой пример этого: запуск сервиса и обращение к нему клиента.
В двух словах об удаленном доступе
Действительно, Spring framework предоставляет богатые возможности как по созданию удаленных служб так и по доступу к ним. На данный момент в распоряжении разработчиков поддержка нескольких моделей удаленного доступа с использованием таких технологий как
- Удаленный вызов процедур (RMI)
- Caucho’s Hessian and Burlap
- Собственная реализация удаленного доступа через HTTP протокол (HTTP invoker)
- Enterprise JavaBeans (EJB)
- Ну и конечно Web службы (JAX-RPC)
Я не буду углубляться в концепцию и детали реализации каждой модели в Spring framework, а всего лишь обозначу основные моменты и приведу небольшой пример по организации удаленного доступа к некой службе с помощью RMI. Более детально обо всем о том, о чем я собираюсь умолчать, можно прочитать в замечательной книге “Spring In Action”
Итак, независимо от выбранной модели, службы можно конфигурировать как Spring-managed бины. Делается это при помощи proxy factory bean-а, который позволяет передавать удаленные службы в качестве значения свойств других бинов так, как будто это обыкновенные локальные объекты. На рисунке показано как это работает.

Клиент вызывает методы у прокси так, как будто прокси реализует функциональность службы. Прокси же в свою очередь взаимодействует с удаленной службой по требованию клиента. Он управляет деталями соединения со службой и выполняет удаленные вызовы к службе.
На серверной стороне Spring позволяет представить функциональность любого Spring-managed бина в виде удаленной службы используя любую из перечисленных выше моделей. На рисунки ниже показано как экспортер представляет методы бина в виде удаленных служб.

Пример экспорта RMI службы
Пришло время показать небольшой пример работы с удаленными службами при помощи Spring. Для начала необходимо определить интерфейс, который будет реализовывать служба, и через который клиент будет обращаться к ней.
package remoting;
public interface HelloWorldService {
String sayHello();
}
Теперь создадим реализацию службы
package remoting.server;
import remoting.HelloWorldService;
public class HelloWorldServiceImpl implements HelloWorldService {
public String sayHello() {
return "HelloWorld";
}
}
Осталось только описать нашу службу в файле конфигурации Spring и экспортировать ее как RMI службу. Однако вместо стандартных процедур генерации стаба и скелетона с использованием rmic и добавления службы вручную в RMI registry, можно воспользоваться классом RmiServiceExporter.
Создаем файл /remoting/server/applicationContext.xml со следующим содержимым
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!--
- Объявляем службу как бин. Обратите внимание что здесь ничего не сказано о том,
- что это удаленная служба. Если необходимо, то эту реализацию можно использовать в
- обычном виде, передав ссылку на нее в необходимые бины.
-->
<bean id="helloWorldService" class="remoting.server.HelloWorldServiceImpl"/>
<!--
- RmiServiceExporter экспортирует любой Spring-managed бин в виде RMI службы. Делает
- он это декорируя бин классом-адаптером. Адаптер затем регистрируется в RMI реестре
- и перправляет удаленные вызовы к службе методам декорируемого бина, в данном случае
- объекту класса HelloWorldServiceImpl
-->
<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
<property name="serviceName" value="HelloWorldService"/>
<property name="service"><ref local="helloWorldService"/></property>
<property name="serviceInterface" value="remoting.HelloWorldService"/>
<property name="registryPort" value="1199"/>
</bean>
</beans>
Ну и наконец создадим загрузчик, который загрузит файл конфигурации и инициирует экспорт службы.
package remoting.server;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloWorldServer {
public static void main(String[] args) {
new ClassPathXmlApplicationContext("/remoting/server/applicationContext.xml");
}
}
Пример клиента RMI службы
RmiProxyFactoryBean - это фабрика, создающая прокси для RMI служб. Ее использование сводится к описанию следующего бина в файле конфигурации Spring:
<bean id="helloWorldService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl" value="rmi://localhost:1199/HelloWorldService"/>
<property name="serviceInterface" value="remoting.HelloWorldService"/>
</bean>
Теперь можно использовать бин helloWorldService как и любой другой “не удаленный” бин, передавая его в другие бины в качестве параметров. Я же приведу пример простейшего клиента, получающего ссылку на helloWorldService из фабрики бинов, загружающей описание из файла конфигурации.
package remoting.client;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import remoting.HelloWorldService;
public class HelloWorldClient {
public static void main(String[] args) {
final ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/remoting/client/applicationContext.xml");
final HelloWorldService service = (HelloWorldService) context.getBean("helloWorldService", HelloWorldService.class);
System.out.println(service.sayHello());
}
}
P.S.
Как видно, Spring framework действительно сильно облегчает работу с удаленными службами. Сегодня я показал, как использовать модель RMI для организации удаленного доступа. В будущем, если в этом есть необходимость, я собираюсь описать использование других моделей, поддерживаемых Spring-ом, а так же рассмотреть преимущества и недостатки разных моделей.
Исходники к данному примеру можно скачать в архиве.
Изменен

Blazkowicz заявил:
Добавлено 4 мая, 2006 в 12:41“В будущем, если в этом есть необходимость, я собираюсь описать использование других моделей, поддерживаемых Spring-ом, а так же рассмотреть преимущества и недостатки разных моделей.”
Дописал бы. Можно было бы статью в RSDN заслать до публикации здесь.
Что думаешь?
lucker (чел в теме) заявил:
Добавлено 4 мая, 2006 в 15:43Допишу.
Sergey заявил:
Добавлено 26 декабря, 2007 в 11:32Интересно посмотреть как это правильно настроить в maven и как запустить на выполнение..
Sergey заявил:
Добавлено 30 декабря, 2007 в 17:18Так же интересно понять, учитывая то, что использование spring позволяет строить приложения подобные тем которые строятся используя ejb - не используя ejb. Например.. на сколько я понял, если создать сервис обернутый в RmiServiceExporter, то этот сервис будет singliton-ом - т.е. аналог stateless-бина (т.е. один для всех).. а как быть если нам нужен аналого statefull-бина. ? (на сколько я понял rmi-сервис всегда будет синглитоном… вопрос - как строить более менее сложные приложения - там где и синглитон и прототайп.. если все так)
lucker (чел в теме) заявил:
Добавлено 12 января, 2008 в 16:57Насчет сервиса, то все зависит от того, к какому скопу (scope) его отнести в соответствующем описании бина. По умолчанию - singletom, но спринг никаким образом не ограничивает полет фантазии - можно использовать и prototype, и любые другие custom scope. По поводу мавена - есть есть необходимость, сделаю maven дескриптор, как вернусь из отпуска.