#java #spring #matlab #cxf
#java #spring #matlab #cxf
Вопрос:
Я пишу веб-сервисы Apache CXF и использую Spring для загрузки своих компонентов. Мой единственный компонент — это вызов внешнего процесса (MATLAB) из Java. Мое определение beans выглядит следующим образом:
<bean id="matlabEngine" class="org.burch.pca.matlab.MatlabEngine"
init-method="start" scope="singleton">
<constructor-arg value="${matlab.engine.path}"></constructor-arg>
</bean>
<bean
class="org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="searchContextAttributes" value="true" />
<property name="contextOverride" value="true" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>classpath:/pca-engine.properties</value>
</list>
</property>
</bean>
Часть моего компонента MatlabEngine выглядит следующим образом:
/**
* Path to MATLAB engine.
*/
private String pathToEngine;
public MatlabEngine(String pathToEngine) throws MatlabConnectionException, MatlabInvocationException{
super();
setPathToEngine(pathToEngine);
}
/**
* Starts engine and goes to path defined by argument
* @param pathToEngine
* @throws MatlabConnectionException
* @throws MatlabInvocationException
*/
public void start() throws MatlabConnectionException, MatlabInvocationException{
//Create a factory
RemoteMatlabProxyFactory factory = new RemoteMatlabProxyFactory();
//Get a proxy, launching MATLAB in the process
proxy = factory.getProxy();
//Display welcoming messages in MATLAB Command Window
proxy.eval(MatlabCommandsRegistry.disp(MATLAB_ENGINE_WELCOME_1));
proxy.eval(MatlabCommandsRegistry.disp(MATLAB_ENGINE_WELCOME_2));
if(pathToEngine!= null amp;amp; !"".equals(pathToEngine)){
logM("Switching to engine directory...");
String goToEngineRootDir = MatlabCommandsRegistry.cd(pathToEngine);
proxy.eval(goToEngineRootDir);
logM("Sucessfully changed engine dir to " pathToEngine);
}
}
Когда я развертываю веб-службы в Tomcat, он прекрасно запускает процесс MATLAB (загружается компонент).
Однако, когда я создаю клиентский запрос к конечной точке веб-службы с помощью этого кода:
public static void main(String args[]) throws Exception {
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.getInInterceptors().add(new LoggingInInterceptor());
factory.getOutInterceptors().add(new LoggingOutInterceptor());
factory.setServiceClass(UploadService.class);
factory.setAddress("http://localhost:8080/auth-ws-1.0.0/services/upload");
UploadService client = (UploadService) factory.create();
UploadEntity resume=new UploadEntity();
resume.setFileName("Image490");
resume.setFileType("jpg");
//Work arround data handler....
DataSource source = new FileDataSource(new File("C:\Users\Pictures\thumb.png"));
DataHandler dataHandle = new DataHandler(source);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
dataHandle.writeTo(stream);
resume.setPayload(stream.toByteArray());
client.uploadFile(resume);
System.exit(0);
}
мой сервер выводит новый экземпляр процесса MATLAB (компонент загружается снова — очень тяжелый и нежелательный). Что я мог бы сделать, чтобы иметь только один компонент, который будет использоваться для обслуживания всей обработки и всех запросов? Я новичок в Spring, и я думаю, что моя проблема в том, что я имею дело с несколькими контекстами здесь. Я хочу, чтобы они совместно использовали один экземпляр одноэлементного компонента, но не знаю, как этим управлять.
Спасибо, что уделили мне время!
Комментарии:
1. Вам действительно нужна функциональность класса ServletContextPropertyPlaceholderConfigurer? Вероятно, вы могли бы вместо этого использовать класс PropertyPlaceholderConfigurer, если вы не пытаетесь анализировать параметры контекста в web.xml .
Ответ №1:
Вы должны включить режим singleton для вашего компонента.
Посмотрите на это: http://static.springsource.org/spring/docs/1.2.x/reference/beans.html#beans-factory-modes
Определение компонента может выглядеть следующим образом:
<!-- Spring property loading bean -->
<bean
class="org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer" singleton="true">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="searchContextAttributes" value="true" />
<property name="contextOverride" value="true" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>classpath:/pca-engine.properties</value>
</list>
</property>
</bean>
Я думаю, вам следует разумно управлять жизненным циклом процесса MATLAB, чтобы уменьшить загрузку ресурсов.
Комментарии:
1. Компоненты Spring по умолчанию являются одиночными. Я решил проблему после того, как понял, что мои компоненты Spring не подключены к конечным точкам веб-службы CXF. Теперь у меня есть только один экземпляр компонента MATLAB engine, и он отлично работает.