Included with WebLogic Server is a sample application, called MedRec (Spring Version), called MedRec-Spring for short. The sample application is based on the WebLogic Server J2EE-based Avitek Medical Records sample application (MedRec). In MedRec-Spring, the J2EE-based Medrec's components are replaced with Spring components, as described in the following sections:
Enable the Spring Web Services Client Service. Spring offers a JAX-WC factory to produce a proxy for Web Services
Use the Spring Transaction Abstraction Layer for Transaction Management.
The sample code in the following sections are from MedRec-Spring.
Note:
MedRec-Spring is not installed by default when you install WebLogic Server. You must choose Custom installation, then select Server Examples from the Choose Products and Component page.If you have already installed WebLogic Server, rerun the installer, select the Middleware home where WebLogic Server is installed, choose Custom installation, then select Server Examples from the Choose Products and Component page.
Included with Medrec-Spring is documentation which discusses its design and implementation. That documentation is available at WL_HOME
\samples\server\docs\
. You can display it from the Windows Start Menu as follows: Start > Programs > Oracle WebLogic > WebLogic Server > Examples > Documentation.
In Spring, references to other beans (injected properties) are configured via the Spring configuration file applicationContext-web.xml
.
Spring 2.5 annotation-driven configuration is used in MedRec-Spring. The application context is configured to have Spring automatically scan the Spring beans detecting Spring-specific annotations like @Service
, so it is not necessary to declare every Spring bean in the XML configuration files. The configuration, in WL_HOME\samples\server\medrec-spring\modules\medrec\web\war\WEB-INF\applicationContext.xml
, is as follows:
<context:component-scan base-package="com.oracle.medrec"/>
The dependency injection is mainly configured via the @Autowired
annotation. For example, the WL_HOME
\samples\server\medrec-spring\modules\medrec\domain\src\com\oracle\medrec\service\impl\RecordServiceImpl.java
includes the following:
@Service("recordService") @Transactional public class RecordServiceImpl implements RecordService { @Autowired private RecordRepository recordRepository; @Autowired private PatientRepository patientRepository; @Autowired private PhysicianRepository physicianRepository;
All of these provide similar development experience as that of EJB 3.0. For more information, see "Annotation Type Autowired" in the Spring documentation at http://www.springsource.org/documentation/
.
MedRec-Spring uses the Spring JaxWsPortProxyFactoryBean
to expose a dynamic proxy for Web Services, as shown in the following example from WL_HOME\samples\server\medrec-spring\modules\physician\web\war\WEB-INF\applicationContext.xml
:
<bean id="patientService" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean"> <property name="serviceInterface" value="com.oracle.physician.service.PatientService"/> <property name="wsdlDocumentUrl" value="http://localhost:7011/medrec/webservices/PatientFacadeService?WSDL"/> <property name="namespaceUri" value="http://www.oracle.com/medrec/"/> <property name="serviceName" value="PatientFacadeService"/> <property name="portName" value="PatientFacadePort"/> </bean> <bean id="physicianService" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean"> <property name="serviceInterface" value="com.oracle.physician.service.PhysicianService"/> <property name="wsdlDocumentUrl" value="http://localhost:7011/medrec/webservices/PhysicianFacadeService?WSDL"/> <property name="namespaceUri" value="http://www.oracle.com/medrec/"/> <property name="serviceName" value="PhysicianFacadeService"/> <property name="portName" value="PhysicianFacadePort"/> </bean> <bean id="recordService" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean"> <property name="serviceInterface" value="com.oracle.physician.service.RecordService"/> <property name="wsdlDocumentUrl" value="http://localhost:7011/medrec/webservices/RecordFacadeService?WSDL"/> <property name="namespaceUri" value="http://www.oracle.com/medrec/"/> <property name="serviceName" value="RecordFacadeService"/> <property name="portName" value="RecordFacadePort"/> </bean>
With this approach, you do not have to use the tool-generated Web Services stubs. For more information, see JaxWsPortProxyFactoryBean
in the Spring documentation at http://www.springsource.org/documentation/
.
In Spring, you must configure JMS services so they are provided to the application during runtime. In MedRec-Spring, Oracle made JMS services available to the application at runtime by implementing the following code in the Spring configuration file WL_HOME\samples\server\medrec-spring\modules\medrec\web\war\WEB-INF\applicationContext.xml
:
<!--- Messaging ************************************* --> <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> <property name="connectionFactory" ref="connectionFactory"/> </bean> <jee:jndi-lookup id="connectionFactory" jndi-name="weblogic.jms.XAConnectionFactory"/> <jee:jndi-lookup id="patientNotificationQueue" jndi-name="com.oracle.medrec.jms.PatientNotificationQueue"/> <bean id="messageListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter"> <property name="delegate" ref="patientNotifierBroker"/> <property name="defaultListenerMethod" value="notifyPatient"/> </bean> <bean id="messageListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> <!--<property name="taskExecutor" ref="taskExecutor"/>--> <property name="connectionFactory" ref="connectionFactory"/> <property name="messageListener" ref="messageListener"/> <property name="destination" ref="patientNotificationQueue"/> <!-- no need to use XA transaction now --> <property name="sessionTransacted" value="true"/> </bean>
Here, various beans from the Spring framework are declared. In particular, the jmsTemplate
wraps the underlying JMS APIs and is used to send messages. messageListenerContainer
provides similar functionality as the Message-Driven Bean container, and the JMS listener in MedRec-Spring is registered to it.
MedRec-Spring use the standard Java Persistence API (JPA) to manage data sources. The configuration is in WL_HOME
\samples\server\medrec-spring\modules\medrec\domain\src\META-INF\persistence.xml
:
<persistence-unit name="MedRec" transaction-type="JTA"> <jta-data-source>jdbc/MedRecGlobalDataSourceXA</jta-data-source> <class>com.oracle.medrec.model.Address</class> <class>com.oracle.medrec.model.Administrator</class> <class>com.oracle.medrec.model.BaseEntity</class> <class>com.oracle.medrec.model.PersonName</class> <class>com.oracle.medrec.model.Patient</class> <class>com.oracle.medrec.model.Physician</class> <class>com.oracle.medrec.model.Prescription</class> <class>com.oracle.medrec.model.Record</class> <class>com.oracle.medrec.model.RegularUser</class> <class>com.oracle.medrec.model.User</class> <class>com.oracle.medrec.model.VersionedEntity</class> <class>com.oracle.medrec.model.VitalSigns</class> <properties> <property name="kodo.jdbc.SynchronizeMappings" value="buildSchema"/> </properties> </persistence-unit>
MedRec-Spring does not declare a Data Access Object (DAO) in the Spring configuration file, because MedRec-Spring uses the annotation-driven approach (in this case @Repository
for all the DAOs), so all of them will be automatically managed by Spring. For example, see the following in RecordRepositoryImpl.java
:
@Repository public class RecordRepositoryImpl extends EntityRepositorySupport<Record, Long> implements RecordRepository { public List<Record> findRecordsByPatientId(Long patientId) { return findByProperty("Record.findRecordsByPatientId", patientId); } }
MedRec-Spring uses Spring 2.5 configuration to use the WebLogic JTA transaction manager and to enable annotation-based declarative transaction management. See the configuration in WL_HOME
\samples\server\medrec-spring\modules\medrec\web\war\WEB-INF\applicationContext.xml
:
<tx:jta-transaction-manager/> <tx:annotation-driven/>
All the transaction demarcation is implemented via Spring's @Transactional
annotation. This is similar to what is done in EJB 3.0 applications. See WL_HOME
\samples\server\medrec-spring\modules\medrec\domain\src\com\oracle\medrec\service\impl\RecordServiceImpl.java
:
@Service("recordService") @Transactional public class RecordServiceImpl implements RecordService { … public void createRecord(Record record, Long physicianId, Long patientId) { } @Transactional(readOnly = true) public List<Record> getRecordsByPatientId(Long patientId) { } @Transactional(readOnly = true) public Record getRecord(Long id) { } }