[UPDATE] This article series has been reedited on the Adobe Developer Connection. For more information, see this post.
In the previous articles in this series, we did the boring stuff of setting up Spring, Hibernate and MySQL on a sample todo list server on one side, and we wrote a small useless Flex UI on the other side. In this article, we’re going to write the final UI and connect it with the Spring backend using BlazeDS. Let’s go!
Creating a module to share configuration files
[EDIT]
This section has been added to avoid duplicating configuration files.
[/EDIT]
The first thing we need to do is to create a new module under todolist. That module will contain our 2 configuration files and package them up in a resource zip that can be included later in both the web and ria modules.
So first go to todolist and run the following command:
mvn archetype:create -DgroupId=org.epseelon.samples -DartifactId=todolist-config
Then go to todolist-config and delete src/main/java and src/main/test directories. After that, create an src/main/resources directory and create services-config.xml in there with the following content:
<?xml version="1.0" encoding="UTF-8"?>
<services-config>
<services>
<service-include file-path="remoting-config.xml" />
</services>
<!-- Spring factory registration -->
<factories>
<factory id="spring"
class="org.epseelon.samples.todolist.controller.SpringFactory" />
</factories>
<channels>
<channel-definition id="channel-amf"
class="mx.messaging.channels.AMFChannel">
<endpoint
url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf"
class="flex.messaging.endpoints.AMFEndpoint" />
<properties>
<polling-enabled>false</polling-enabled>
</properties>
</channel-definition>
</channels>
<logging>
<target class="flex.messaging.log.ConsoleTarget"
level="Error">
<properties>
<prefix>[BlazeDS]</prefix>
<includeDate>true</includeDate>
<includeTime>false</includeTime>
<includeLevel>true</includeLevel>
<includeCategory>true</includeCategory>
</properties>
<filters>
<pattern>Endpoint.*</pattern>
<pattern>Service.*</pattern>
<pattern>Message.*</pattern>
<pattern>DataService.*</pattern>
<pattern>Configuration</pattern>
</filters>
</target>
</logging>
<system>
<redeploy>
<enabled>true</enabled>
<watch-interval>20</watch-interval>
<watch-file>
{context.root}/WEB-INF/flex/services-config.xml
</watch-file>
<watch-file>
{context.root}/WEB-INF/flex/remoting-config.xml
</watch-file>
<touch-file>{context.root}/WEB-INF/web.xml</touch-file>
</redeploy>
</system>
</services-config>
Next in the same directory, create a file named remoting-config.xml with the following content:
<?xml version="1.0" encoding="UTF-8"?>
<service id="remoting-service"
class="flex.messaging.services.RemotingService">
<adapters>
<adapter-definition id="java-object"
class="flex.messaging.services.remoting.adapters.JavaAdapter"
default="true" />
</adapters>
<default-channels>
<channel ref="channel-amf" />
</default-channels>
<destination id="todoService">
<properties>
<factory>spring</factory>
<source>todoService</source>
</properties>
</destination>
</service>
Now you need to edit todolist-config/pom.xml like this:
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>todolist</artifactId>
<groupId>org.epseelon.samples</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.epseelon.samples</groupId>
<artifactId>todolist-config</artifactId>
<name>todolist-config</name>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>make shared resources</id>
<goals>
<goal>single</goal>
</goals>
<phase>package</phase>
<configuration>
<descriptors>
<descriptor>src/main/assembly/resources.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Notice the pom packaging and configuration of maven assembly plugin to package configuration according to the assembly descriptor in src/main/assembly/resources.xml file as follows:
<assembly>
<id>resources</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>src/main/resources</directory>
<outputDirectory></outputDirectory>
</fileSet>
</fileSets>
</assembly>
Now you can run ‘mvn install’ and you see a file called todolist-config-1.0-SNAPSHOT-resources.zip, with just our 2 configuration file inside.
Exposing Spring service via BlazeDS
The next thing to do is to add BlazeDS libraries to our web module dependencies. To do that, edit todolist-web/pom.xml and add the following dependencies:
<dependency> <groupId>com.adobe.blazeds</groupId> <artifactId>blazeds-common</artifactId> <version>3.0.0.544</version> </dependency> <dependency> <groupId>com.adobe.blazeds</groupId> <artifactId>blazeds-core</artifactId> <version>3.0.0.544</version> </dependency> <dependency> <groupId>com.adobe.blazeds</groupId> <artifactId>blazeds-remoting</artifactId> <version>3.0.0.544</version> </dependency> <dependency> <groupId>backport-util-concurrent</groupId> <artifactId>backport-util-concurrent</artifactId> <version>3.1</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency>
blazeds-core, blazeds-common and blazeds-remoting are only available from my personal repository for now, until Adobe publishes them to a public repository. Now that BlazeDS libraries have been added to the project, we’ll add a special Java class to the project. This class will act as a bridge between BlazeDS and Spring by retrieving Spring bean instances for BlazeDS FlexFactory interface. Here comes the org.epseelon.samples.todolist.controller.SpringFactory class (curtesy of Jeff Wroom):
package org.epseelon.samples.todolist.controller;
import flex.messaging.FactoryInstance;
import flex.messaging.FlexFactory;
import flex.messaging.config.ConfigMap;
import flex.messaging.services.ServiceException;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
public class SpringFactory implements FlexFactory {
private static final String SOURCE = "source";
public void initialize(String id, ConfigMap configMap) {
}
public FactoryInstance createFactoryInstance(String id, ConfigMap properties) {
SpringFactoryInstance instance = new SpringFactoryInstance(this, id, properties);
instance.setSource(properties.getPropertyAsString(SOURCE, instance.getId()));
return instance;
} // end method createFactoryInstance()
public Object lookup(FactoryInstance inst) {
SpringFactoryInstance factoryInstance = (SpringFactoryInstance) inst;
return factoryInstance.lookup();
}
static class SpringFactoryInstance extends FactoryInstance {
SpringFactoryInstance(SpringFactory factory, String id, ConfigMap properties) {
super(factory, id, properties);
}
public String toString() {
return "SpringFactory instance for id=" + getId() + " source=" + getSource() + " scope=" +
getScope();
}
public Object lookup() {
ApplicationContext appContext = WebApplicationContextUtils.getWebApplicationContext(flex.messaging.FlexContext.getServletConfig().getServletContext());
String beanName = getSource();
try {
return appContext.getBean(beanName);
} catch (NoSuchBeanDefinitionException nexc) {
ServiceException e = new ServiceException();
String msg = "Spring service named '" + beanName
+ "' does not exist.";
e.setMessage(msg);
e.setRootCause(nexc);
e.setDetails(msg);
e.setCode("Server.Processing");
throw e;
} catch (BeansException bexc) {
ServiceException e = new ServiceException();
String msg = "Unable to create Spring service named '"
+ beanName + "' ";
e.setMessage(msg);
e.setRootCause(bexc);
e.setDetails(msg);
e.setCode("Server.Processing");
throw e;
}
}
}
}
Now we’ll configure the servlet that is responsible for handling remoting requests coming from the Flex UI and calling the Spring service accordingly. Add the following configuration to todolist-web/src/main/webapp/WEB-INF/web.xml, just after listener configuration:
<context-param>
<param-name>flex.class.path</param-name>
<param-value>/WEB-INF/flex/hotfixes</param-value>
</context-param>
<!-- MessageBroker Servlet -->
<servlet>
<servlet-name>MessageBrokerServlet</servlet-name>
<servlet-class>
flex.messaging.MessageBrokerServlet
</servlet-class>
<init-param>
<param-name>services.configuration.file</param-name>
<param-value>/WEB-INF/flex/services-config.xml</param-value>
</init-param>
<init-param>
<param-name>flex.write.path</param-name>
<param-value>/WEB-INF/flex</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>MessageBrokerServlet</servlet-name>
<url-pattern>/messagebroker/*</url-pattern>
</servlet-mapping>
As you can see, this servlet needs some configuration files to work, more specifically the files that are in our shared configuration module.
In order to import these files, we need to include our shared configuration module as a dependency of the web module. To do this, add the following dependency to todolist-web/pom.xml:
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>todolist-config</artifactId>
<version>1.0-SNAPSHOT</version>
<classifier>resources</classifier>
<type>zip</type>
<scope>provided</scope>
</dependency>
Then, in order to unpack those configuration files and embed them in your web application, you need to add the following plugin configuration to the build section in todolist-web/pom.xml:
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-config</id>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<phase>generate-resources</phase>
<configuration>
<outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/flex</outputDirectory>
<includeArtifacIds>todolist-config</includeArtifacIds>
<includeGroupIds>${project.groupId}</includeGroupIds>
<includeClassifiers>resources</includeClassifiers>
<excludeTransitive>true</excludeTransitive>
<excludeTypes>jar,swf</excludeTypes>
</configuration>
</execution>
</executions>
</plugin>
Now, you can have a look at todolist-config/src/main/resources/services-config.xml. Here the most interesting part is the destination configuration: we define a todoService destination that uses our SpringFactory for handling and the source parameter corresponds to the bean id of the service.
There is one more thing to do in order to allow Maven to build todolist-web independently from other modules. flex-compiler-mojo defines a resource-bundle packaging that maven-war-plugin is not aware of. And you have to add the following plugin configuration to solve that issue:
<plugin>
<groupId>info.rvin.mojo</groupId>
<artifactId>flex-compiler-mojo</artifactId>
<extensions>true</extensions>
</plugin>
Last but not least, run ‘mvn install’ to check that everything is working, and that both configuration files are present in WEB-INF/flex.
That’s it. Now our todo service is exposed for remoting via BlazeDS. Let’s move on to the client-side connection.
Writing the Flex UI
First off, delete todolist-ria/src/main/flex/Main.xml and create todolist-ria/src/main/flex/index.mxml with the following content:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical" verticalAlign="middle" horizontalAlign="center"
xmlns:screen="org.epseelon.samples.todolist.view.screen.*">
<screen:TodoForm/>
</mx:Application>
The main screen is a TodoForm class that you have to create in todolist-ria/src/main/flex/org/epseelon/samples/todolist/view/screen/TodoForm.mxml:
<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical" width="488" height="384" creationComplete="getList()">
<mx:Form width="100%" height="100%" defaultButton="{saveButton}">
<mx:FormHeading label="Todo List" width="100%"/>
<mx:FormItem label="ID:" width="127">
<mx:TextInput width="100%" id="idText"
text="{TodoItem(todoDatagrid.selectedItem).id}" editable="false" enabled="false"/>
</mx:FormItem>
<mx:FormItem label="Title:" width="345">
<mx:TextInput width="100%" id="titleText"
text="{TodoItem(todoDatagrid.selectedItem).title}"/>
</mx:FormItem>
<mx:DataGrid id="todoDatagrid" width="100%" height="100%" dataProvider="{todoItems}">
<mx:columns>
<mx:DataGridColumn headerText="ID" dataField="id" width="30"/>
<mx:DataGridColumn headerText="Title" dataField="title"/>
</mx:columns>
</mx:DataGrid>
</mx:Form>
<mx:ControlBar horizontalAlign="center">
<mx:Button label="New" click="setDefault()"/>
<mx:Button label="Save" id="saveButton" click="save()"
textAlign="center"/>
<mx:Button label="Delete" click="remove()"/>
</mx:ControlBar>
<mx:RemoteObject id="todoService" showBusyCursor="true"
fault="onFault(event)" destination="todoService">
<mx:method name="save" result="onResultSave(event)" fault="onFault(event)"/>
<mx:method name="remove" result="onResultRemove(event)" fault="onFault(event)"/>
<mx:method name="getList" result="onResultGetList(event)" fault="onFault(event)"/>
</mx:RemoteObject>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import org.epseelon.samples.todolist.view.entity.TodoItem;
import mx.rpc.events.ResultEvent;
import mx.rpc.events.FaultEvent;
import mx.controls.Alert;
[Bindable]
private var todoItems:ArrayCollection;
private var todoItem:TodoItem;
public function save():void
{
this.todoItem = new TodoItem();
this.todoItem.id = new Number(idText.text);
this.todoItem.title = titleText.text;
todoService.save(todoItem);
}
public function onResultSave(event:ResultEvent):void
{
status = "Item was successfully saved with ID: " + TodoItem(event.result).id;
getList();
}
public function remove():void
{
if (todoDatagrid.selectedItem != null) {
todoItem = todoDatagrid.selectedItem as TodoItem;
todoService.remove(todoItem);
} else {
Alert.show("Select an item to delete");
}
}
public function onResultRemove(event:ResultEvent):void
{
status = "Deletion succeeded!";
getList();
}
public function getList():void
{
todoService.getList();
}
public function onResultGetList(event:ResultEvent):void
{
todoItems = event.result as ArrayCollection;
}
public function setDefault():void
{
idText.text = "";
titleText.text = "";
}
//Ocorreu uma falha ao chamar algum servico servico.
public function onFault(event:FaultEvent):void
{
Alert.show(event.fault.message);
}
]]>
</mx:Script>
</mx:TitleWindow>
The first part of this view is a simple form with two text fields to contain the ID and the title of the item being edited or created, and a list of all todo items.
Then you have a control bar with all the buttons necessary to create, update and delete items.
The third part is the remote object that is used to call methods on the server. As you can see, it references the todoService destination and defines the three methods to save, delete and list items, with their corresponding result and fault handlers.
Finally, we have the ActionScript part that implements methods to call the server, result and fault handlers. As you can see, all those methods use the org.epseelon.samples.todolist.view.entity.TodoItem class, that is really an exact ActionScript mapping for the org.epseelon.samples.todolist.domain.TodoItem class on the server-side. Here it goes:
package org.epseelon.samples.todolist.view.entity
{
[RemoteClass(alias="org.epseelon.samples.todolist.domain.TodoItem")]
[Bindable]
public class TodoItem
{
public var id:Number;
public var title:String;
}
}
Now what is really cool is that BlazeDS will automatically serialize into and deserialize from this class for us, so that we only have to manipulate this version in our client.
Compiling the Flex UI
Since our Flex UI defines a remote object that references our todoService destination, we need to compile index.mxml with a few additional parameters.
First, the compiler needs to know where it can find the services-config.xml file where todoService destination is defined. You can add a <services/> element to the flex-compiler-mojo configuration section. But here, we are going to use the default setting, which causes the plugin to look for a file named services-config in the module resources. And to avoid duplicating those files, we will just add our shared configuration module as a dependency of todolist-ria:
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>todolist-config</artifactId>
<version>1.0-SNAPSHOT</version>
<classifier>resources</classifier>
<type>zip</type>
<scope>provided</scope>
</dependency>
And in order to unpack the files in resources, add the following plugin configuration to todolist-ria/pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-config</id>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<phase>generate-resources</phase>
<configuration>
<outputDirectory>${project.build.directory}/generated-resources</outputDirectory>
<includeArtifacIds>todolist-config</includeArtifacIds>
<includeGroupIds>${project.groupId}</includeGroupIds>
<excludeTransitive>true</excludeTransitive>
</configuration>
</execution>
</executions>
</plugin>
Now we need to add target/generated-resources to default resources by adding the following section in build:
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
</resource>
<resource>
<directory>${basedir}/target/generated-resources</directory>
<filtering>true</filtering>
</resource>
</resources>
Last but not least, our remote object will send its AMF request messages to the same host and same port than the one on which the SWF is running. But we still need to specify the context root where the MessageBrokerServlet will receive those messages. This context root value will be used as a placeholder in the channel definition in services-config.xml. To specify a value for this parameter, all we have to do is to modify the configuration for the flex-compiler-mojo in todolist-ria/pom.xml:
<plugin>
<groupId>info.rvin.mojo</groupId>
<artifactId>flex-compiler-mojo</artifactId>
<version>1.0-alpha7</version>
<extensions>true</extensions>
<configuration>
<locales>
<param>en_US</param>
</locales>
<contextRoot>todolist-web</contextRoot>
</configuration>
</plugin>
By the way, you can notice that the value for the context root corresponds to the build/finalName parameter defined in todolist-web/pom.xml. Now you can run ‘mvn install’ on the whole project.
Note that by default, flex-compiler-mojo will look for the one mxml file in src/main/flex as the main application. If there are several mxml files there, it will take any file called main.as or main.mxml as the main application. And because Velo really understood that Maven is all about “convention over configuration”, you can also specify your own path for this main file using the ’sourceFile’ configuration parameter. Ain’t that awesome?
Ready for the final steps?
Bundling the Flex UI into the web application
Now we need to include our Flex UI as a dependency in our web module. To do so, add the following dependency to todolist-web/pom.xml:
<dependency> <groupId>org.epseelon.samples</groupId> <artifactId>todolist-ria</artifactId> <version>1.0-SNAPSHOT</version> <type>swf</type> </dependency>
Now if we want this dependency to be copied over to our web archive, we need to configure maven-dependency-plugin to do so. So you can add this execution to the maven-dependency-plugin configuration in todolist-web/pom.xml:
<execution>
<id>copy-swf</id>
<phase>process-classes</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/${project.build.finalName}</outputDirectory>
<includeTypes>swf</includeTypes>
</configuration>
<execution>
There are still a few things we need to do, just to make it easier to access our application. First, edit todolist-web/src/main/webapp/index.jsp and put the following content:
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- BEGIN Browser History required section -->
<link rel="stylesheet" type="text/css" href="history/history.css" />
<!-- END Browser History required section -->
<title>Todo List</title>
<script src="AC_OETags.js" language="javascript"></script>
<!-- BEGIN Browser History required section -->
<script src="history/history.js" language="javascript"></script>
<!-- END Browser History required section -->
<style>
body { margin: 0px; overflow:hidden }
</style>
<script language="JavaScript" type="text/javascript">
<!--
// -----------------------------------------------------------------------------
// Globals
// Major version of Flash required
var requiredMajorVersion = 9;
// Minor version of Flash required
var requiredMinorVersion = 0;
// Minor version of Flash required
var requiredRevision = 28;
// -----------------------------------------------------------------------------
// -->
</script>
</head>
<body scroll="no">
<script language="JavaScript" type="text/javascript">
<!--
// Version check for the Flash Player that has the ability to start Player Product Install (6.0r65)
var hasProductInstall = DetectFlashVer(6, 0, 65);
// Version check based upon the values defined in globals
var hasRequestedVersion = DetectFlashVer(requiredMajorVersion, requiredMinorVersion, requiredRevision);
if ( hasProductInstall && !hasRequestedVersion ) {
// DO NOT MODIFY THE FOLLOWING FOUR LINES
// Location visited after installation is complete if installation is required
var MMPlayerType = (isIE == true) ? "ActiveX" : "PlugIn";
var MMredirectURL = window.location;
document.title = document.title.slice(0, 47) + " - Flash Player Installation";
var MMdoctitle = document.title;
AC_FL_RunContent(
"src", "playerProductInstall",
"FlashVars", "MMredirectURL="+MMredirectURL+'&MMplayerType='+MMPlayerType+'&MMdoctitle='+MMdoctitle+"",
"width", "100%",
"height", "100%",
"align", "middle",
"id", "index",
"quality", "high",
"bgcolor", "#869ca7",
"name", "index",
"allowScriptAccess","sameDomain",
"type", "application/x-shockwave-flash",
"pluginspage", "http://www.adobe.com/go/getflashplayer"
);
} else if (hasRequestedVersion) {
// if we've detected an acceptable version
// embed the Flash Content SWF when all tests are passed
AC_FL_RunContent(
"src", "todolist-ria-1.0-SNAPSHOT",
"width", "100%",
"height", "100%",
"align", "middle",
"id", "todolist-ria-1.0-SNAPSHOT",
"quality", "high",
"bgcolor", "#869ca7",
"name", "todolist-ria-1.0-SNAPSHOT",
"allowScriptAccess","sameDomain",
"type", "application/x-shockwave-flash",
"pluginspage", "http://www.adobe.com/go/getflashplayer"
);
} else { // flash is too old or we can't detect the plugin
var alternateContent = 'Alternate HTML content should be placed here. '
+ 'This content requires the Adobe Flash Player. '
+ '<a href=http://www.adobe.com/go/getflash/>Get Flash</a>';
document.write(alternateContent); // insert non-flash content
}
// -->
</script>
<noscript>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
id="index" width="100%" height="100%"
codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">
<param name="movie" value="index.swf" />
<param name="quality" value="high" />
<param name="bgcolor" value="#869ca7" />
<param name="allowScriptAccess" value="sameDomain" />
<embed src="todolist-ria-1.0-SNAPSHOT.swf" quality="high" bgcolor="#869ca7"
width="100%" height="100%" name="index" align="middle"
play="true"
loop="false"
quality="high"
allowScriptAccess="sameDomain"
type="application/x-shockwave-flash"
pluginspage="http://www.adobe.com/go/getflashplayer">
</embed>
</object>
</noscript>
</body>
</html>
This code comes from the standard HTML template generated by Flex Builder and uses javascript to embed the SWF object into a traditional web page. Of course, we need to add the files this pages depends on. First download AC_OETags.js and copy it to todolist-web/src/main/webapp/AC_OETags.js.
Then download playerProductInstall.swf and put it in the same directory.
Lastly, download history.zip and unzip it in the same directory.
That’s it, now everything is ready. You can now run ‘mvn install’ for the last time, deploy todolist-web.war to JBoss or Tomcat, start your server and go to http://localhost:8080/todolist-web…
And it should work!
And because I’m a good boy, I’m even going to give you the final version of this project with everything inside. Enjoy!
Conclusion
This project setup certainly requires a bit of work, but in the end, set aside this small issue with configuration file duplication that should be fixed soon, it’s pretty clean, and flex-compiler-mojo works really great.
Now of course, we can add many things like flexunit tests, asdoc generation and so on, but for now, I just wanted to focus on the configuration needed for BlazeDS to work.
Now I’m waiting for your feedback, questions, suggestions, and I’ll probably edit those articles as it comes until it’s good enough to be published… somewhere else.
In the meantime, I’d like to thank Velo for providing this great plugin as well as the support I needed from him to write this tutorial.
Ready for comments? Shoot!
This content is published under the Attribution-Noncommercial-Share Alike 3.0 Unported license.



Posted in
Tags: 
You mention not including mysql-connector-java-5.1.6.jar as a dependency but rather manually putting this in the lib folder. How can this be automated? We really need to remove all manual steps, what are the options? Why not include as dependency?
@Dave
Because JDBC is not an application-specific library. Well, it rarely is anyway. Actually the best way to deal with it would be to share it the OSGi way. But in the meantime it’s just best practice to have JDBC part of your system environmen, that is your application server. And it’s not included in JBoss or Tomcat by default because it depends on your preferred database system.
@Dave
I don’t know exactly what you modified but the javascript that embeds the SWF in the HTML is tricky. The full name of the SWF is never mentioned. And there are references you must update, others that you shouldn’t touch. I don’t remember exactly and I don’t have the html template here. But you can can easily try and see by updating one reference at a time.
As for the database reference, did you disable the transaction manager too? Because that’s what creates the Hibernate/JPA session and if you don’t disable those, you’re in trouble. The thing is that there are a lot of things that happen automagically with Spring 2, and I’m not always convinced it’s a good thing, especially for people who don’t understand how Spring works under the hood, it can be tricky.
I only modified the jsp page as I think that is the only custom page. There are several places where it uses names like “sample-ria-1.0-SNAPSHOT”, this is what I modified. I think in one place it has the .swf extension.
As for Spring, I commented out everything except:
Perhaps it is a Spring problem, I don’t know the majic it does. I just deleted the entries that were db/transaction related as that seemed like the right thing to do.
I did get your sample working with my changes when I started with your downloadable project, in this later case the db stuff is still there it just fails at runtime because I don’t have that db loaded.
P.S. I would like to know what happened in the first attempt because I’m afraid if I don’t know the cause, it will happen again. But that might not be possible.
Also, if I keep going with this approach I would like to automate the editing of the jsp page and perhaps all the static web files should be yet another maven module so it all gets added automatically.
Oops, the blog tool stripped out my spring xml code, lets try it again.
As for Spring, I commented out everything except:
”
“
Hum, I don’t know how to post xml. So I’ll just say what I do in Spring.
I have one bean id=todoService mapped to class=TodoServiceImpl. Everything else was commented out.
if you have not resolved the issue with flex mojo’s with chart. there here is the solution:
How to use charts or advanced datagrid?
Is necessary to add data visualization dependencies:
com.adobe.flex.sdk
datavisualization
3.0.0.3.0.0.477
swc
com.adobe.flex.sdk
datavisualization
3.0.0.3.0.0.477
resource_bundle
en_US
[top]
How to remove “Flex Charting Trial” water mark?
In order to do that, you must have Charts license.
Them, just add licenses configuration to your pom.xml, like this:
…
info.rvin.mojo
flex-compiler-mojo
…
put-your-license-here
Hello,
I have build a webapp based on your tutorial. Unfortunately I overlooked that part where you said it is good only when we have one entity in the system. Now its too late and I have big problems with LazyInitializationException. I made Many-to-Many relationships in hibernate and there is a problem with sessions. Is it complicated to upgrade todolist app to use more then one entity? You said that it is possible to add everything later. Could you post more details?
My webapp is a part of my master thesis and I really need it working. So if you could give me some tips it would be great. (I need to mention that it is my first webapp in this technologies so not everything id clear to me at once).
Great series! If you have some thoughts on the benefits that you reap with this setup that would great :)
Hello Sébastien,
Thanks for this series of articles. I have successfully created a full project that includes Java and Flex.
However, I am wondering now how to integrate this in Eclipse. I would like to be able to code and deploy in Eclipse.
I checked Eclipse WTP tutorials, but they all recommend to create a Flex / J2EE project from scratch, and I can’t find anything on how to integrate a project with the structure we just built.
Do you have an idea on how to accomplish this?
Thanks for your posts,
–
Sébastien
[...] Hibernate, MySQL and a Maven build (2, 3rd part is still not published; Original series: 1, 2, 3, 4, [...]