The Spring Framework aka Spring, is an open source java application framework. Signature services of the Spring Framework include Inversion of Control (IoC) and Aspect-oriented programming (AOP). For more information about Spring and SpringSource, see SpringSource.org.
WaveMaker is built upon Spring. Project services are all created as XML declared spring beans. A bean is an object that is instantiated, assembled, and otherwise managed by a Spring IoC container. Otherwise, a bean is simply one of many objects in your application. ref
Example project export SpringIntegrationFileServerExample.zip (version 6.3) This example takes Josh Long's file system example and integrates it into WaveMaker. The spring example source is available from src.springframework.org NOTE: This example uses the project java service as the service activator. The service activator would normally not be exposed the client. This example also demonstrates that we can use component scanning and the @Component stereotype annotation in project service classes. The following sections walk through how the example was built
Congratulations. You have integrated Spring Integration into your WaveMaker project.
To understand the failure, look for errors prior to testrunstart. This is where you will find parser errors such as:
The log4j.properties file includes three spring framework loggers. Enabling these to debug is very verbose.
Webinar
View Recording Slides from Webinar (PDF)Dependency Injection
In dependency injection (DI), beans declare their dependencies and the container server passes or injects those objects (parameters) to your java objects (project services). Using dependency injection with your java code in WaveMaker is simple. You only need to declare the member in your class and the property reference in your bean declaration.DI Example
This example shows getting the JDBC URL of an imported data model in a java service using setter-based injection. This would be used if we wanted to perform database operations directly from our java service. See also using a database service from java to use existing connections. Example project DependencyInjectionJDBC.zip (WaveMaker 6.3)Import a Database
In this example we import the HSQLDB database "Rolodex"Add java service
We called our service: MyDataService With a package and class of: dev.wavemaker.example.MyDataService Leave the class to the default generated for now and save to complete generation.Determine property to be injected
Open \services\rolodex\src\rolodex.spring.xml Find the SessionFactory property name. This is usually on line 78 for imported database services. For this example, we want the dataSource property. com.wavemaker.runtime.data.spring.ConfigurationAndSessionFactoryBean is the wavemaker class that extends org.springframework.orm.hibernate3.LocalSessionFactoryBean We want the same dataSource provided to the SessionFactory rolodex.spring.xml:<!-- A unique name for this SessionFactory's configuration --> <property name="name" value="rolodex"/> <property name="dataSource" ref="rolodexDataSource"/>
Modify java service definition
Open servicesMyDataServiceMyDataService.spring.xml and make the following modifications:- Import rolodex.spring.xml
- Add the dataSource property from the rolodexDataSource
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <beans xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd" xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <!-- Import Added --> <import resource="classpath:rolodex.spring.xml"/> <!-- trailing "/" at column 108 removed so we add property--> <bean lazy-init="true" scope="singleton" class="dev.wavemaker.example.MyDataService" id="MyDataService"> <!-- dataSource property, ref bean and closing /bean added--> <property name="dataSource"> <ref bean="rolodexDataSource"/> </property> <!-- replaces / removed from line 7 --> </bean> <!-- No modifications beyond this point--> <bean lazy-init="false" scope="singleton" class="com.wavemaker.runtime.service.reflect.ReflectServiceWire"> <property value="MyDataService" name="serviceId"/> <property ref="JavaService" name="serviceType"/> </bean> </beans>
Implement Java Service
Now we can fully implement our java service. In this example we use a required setter for injection.package dev.wavemaker.example; import com.wavemaker.common.WMRuntimeException; import com.wavemaker.runtime.service.annotations.ExposeToClient; import com.wavemaker.runtime.service.annotations.HideFromClient; import org.springframework.beans.factory.annotation.Required; import org.springframework.jdbc.datasource.DriverManagerDataSource; import java.util.Collection; import java.util.List; import java.util.ArrayList; import java.sql. * ; /** * This is an example of using dependency injection to get the JDBC connection URL from an imported database service * This class might use the dataSource to open it's own connection to the database. * */ public class MyDataService extends com.wavemaker.runtime.javaservice.JavaServiceSuperClass { private Connection conn; private DriverManagerDataSource dataSource; // Setter for dataSource injection by container // Using @Required to ensure depenendcy is set // Using @HideFromClient to prevent IllagalArgumentException in 6.3, fixed for 6.4 @HideFromClient @Required public void setDataSource(DriverManagerDataSource dataSource) { this.dataSource = dataSource; } // The @HideFromClient annoation prevents the error // IllegalArgumentException: com.wavemaker.json$NoGetterInType: args don't match. msg requires: 3 passed in: 1 // Not needed with WM 6.4 @HideFromClient public Connection getConnection() { try { if (conn == null) conn = dataSource.getConnection(); } catch (SQLException e) { e.printStackTrace(); throw new WMRuntimeException(e); } return conn; } // Method for returning URL to client for demo // public methods are exposed to client by default public String getURL() { String result = null; try { conn = this.getConnection(); result = conn.getMetaData().getURL(); } catch (SQLException e) { e.printStackTrace(); throw new WMRuntimeException(e); } return result; } //For logging, extension of JavaServiceSuperClass is optional public MyDataService() { super(INFO); } }
Spring Integration 2.0
Example of using Spring IntegrationExample project export SpringIntegrationFileServerExample.zip (version 6.3) This example takes Josh Long's file system example and integrates it into WaveMaker. The spring example source is available from src.springframework.org NOTE: This example uses the project java service as the service activator. The service activator would normally not be exposed the client. This example also demonstrates that we can use component scanning and the @Component stereotype annotation in project service classes. The following sections walk through how the example was built
Add jar files to lib
Download Spring Integration and copy:- spring-integration-core-2.0.4.RELEASE.jar
- spring-integration-file-2.0.4.RELEASE.jar
Add Java Service to project
Add a Java Service to the project. In this example the Service name is ServerFileProcessor and the class and package name is dev.wavemaker.fileProcessing.InboundFileProcessor Here is our InboundFileProcessor classpackage dev.wavemaker.fileProcessing; import org.springframework.integration.annotation.*; import org.springframework.stereotype.Component; import java.io.File; import java.util.Map; /** * Based on the example from: * http://blog.springsource.com/2010/08/23/secure-file-transfer-the-only-way-to-fly/ * * Copy spring-integration-core-2.x to project lib folder for this to compile * */ @Component //Already a bean since using project service public class InboundFileProcessor { @ServiceActivator public void onNewFileArrival( @Headers Map<String, Object> headers, @Payload File file) { System.out.printf("***\t A new file has arrived deposited into " + "the inbox folder at the absolute " + "path %s \n", file.getAbsolutePath()); System.out.println("The headers are:"); for (String k : headers.keySet()) System.out.println(String.format("%s=%s", k, headers.get(k))); } }
Define Service Activator
Save this as ServerFileProcessor.xml in WEB-INF This file defines the inbound file adapter, mapping the arrival of files to your service-activator<beans:beans
xmlns="http://www.springframework.org/schema/integration"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:file="http://www.springframework.org/schema/integration/file"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/integration/file http://www.springframework.org/schema/integration/file/spring-integration-file-2.0.xsd">
<context:component-scan base-package="dev.wavemaker.fileProcessing"/>
<channel id="inboundFiles"/>
<file:inbound-channel-adapter channel="inboundFiles"
auto-create-directory="true"
filename-pattern="test*"
directory="#{systemProperties['user.home']}/Inbox">
<poller fixed-rate="10000"/>
</file:inbound-channel-adapter>
<service-activator input-channel="inboundFiles" ref="ServerFileProcessor" method="onNewFileArrival"/>
</beans:beans>Import ServerFileProcessor.xml
In project-spring.xml import ServerFileProcessor.xml<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <!-- Import our Integration config --> <import resource="ServerFileProcessor.xml"/> </beans>
Run and Test
Run the project. If the project fails to deploy, you have an error, probably in the xml. To see details about the error, view the wm.log file. XML errors are logged before the testrunstart and failed to start error. Our ServerFileProcessor.xml specifies that Spring Integration will auto create the inbox directory in your user home folder. The poller is set to every 10 seconds looking for files starting with test. Save a file to the inbox folder in user home with a file name that starts with "test". In the wm.log you should see a message from the onNewFileArrival function:*** A new file has arrived deposited into the inbox folder at the absolute path C:\Users\ecallahan\Inbox\testme.txt
The headers are:
timestamp=1311722647762
id=841fe34e-cdf9-4ac0-bb19-84c56d29378cTroubleshooting
The most common problems are with XML errors. These will cause the application to fail to startFAIL - Deployed application at context path /TestSI but context failed to start
Caused by: org.xml.sax.SAXParseException: Element type "import" must be followed by either attribute specifications, ">" or "/>".
## Spring log4j.category.org.springframework=debug # Spring ClassUtils #log4j.logger.org.springframework.util.ClassUtils=debug log4j.category.org.springframework.web.servlet.view=debug
on 11/08/2011 at 06:37


