PDA

View Full Version : Help with Spring BlazeDS configuration



macdoug1
Jan 7th, 2009, 02:27 PM
In the examples from Jeremy on this config setup I see this: web-application-config.xml file. Is this file taking the place of the applicationContext.xml? I'm not really sure what the purpose of this file is; as there is no real explanation on it in the docs. I have setup my Spring app. to use iBatis and I'm trying to use the BlazeDS integration to talk to my serviceImpl.I unfortunately have a gap in my understanding of how this is wired together from the perspective of the applicationContext.xml and the web.xml with this file mentioned above(web-application-config.xml). In your article here: http://blog.springsource.com/2008/12/17/using-spring-blazeds-integration-m1/ some of your files are unclear as to what configuration block is going where.

Anyway I'm using JDK1.5, Spring2.5.5,BlazeDS3.2 -
Here is my applicationContext.xml

<!--
- Nestle primary business object (default implementation).
- Transaction advice gets applied through the AOP configuration below.
-->
<bean id="nestleDataService" class="com.talisen.domain.logic.NestleDataServiceImpl">
<property name="accountDao" ref="accountDao"/>
<property name="buildingDao" ref="buildingDao"/>
<property name="electricDao" ref="electricDao"/>
</bean>

<!-- Expose the nestleDataService bean foro BlazeDS remoting -->
<bean id="nestleService"
class="org.springframework.flex.messaging.remoting.FlexRe motingServiceExporter">
<property name="messageBroker" ref="mySpringManagedMessageBroker"/>
<property name="service" ref="nestleDataService"/>
</bean>

<!-- Maps request paths at /messagebroker to the BlazeDS MessageBroker -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlH andlerMapping">
<property name="mappings">
<value>
/messagebroker/*=mySpringManagedMessageBroker
</value>
</property>
</bean>

<!-- Dispatches requests mapped to a MessageBroker -->
<bean class="org.springframework.flex.messaging.servlet.Message BrokerHandlerAdapter"/>

and of course the web.application-config.xml as mentioned in your post as well as the remoting-config.xml, services-config.xml and remoting-config.xml.
Here is the web.xml-

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<display-name>Nestle Data Service</display-name>

<description>Nestle Data Application</description>

<!--
- Key of the system property that should specify the root directory of this
- web app. Applied by WebAppRootListener or Log4jConfigListener.
-->
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>nestle.root</param-value>
</context-param>


<!--
- Location of the Log4J config file, for initialization and refresh checks.
- Applied by Log4jConfigListener.
-->
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/log4j.properties</param-value>
</context-param>

<!--
- Location of the XML file that defines the root application context.
- Applied by ContextLoaderServlet.
-
- Can include "/WEB-INF/dataAccessContext-local.xml" for a single-database
- context, or "/WEB-INF/dataAccessContext-jta.xml" for a two-database context.
-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/dataAccessContext-local.xml /WEB-INF/applicationContext.xml</param-value>

</context-param>

<!--
- Configures Log4J for this web app.
- As this context specifies a context-param "log4jConfigLocation", its file path
- is used to load the Log4J configuration, including periodic refresh checks.
-
- Would fall back to default Log4J initialization (non-refreshing) if no special
- context-params are given.
-
- Exports a "web app root key", i.e. a system property that specifies the root
- directory of this web app, for usage in log file paths.
- This web app specifies "petclinic.root" (see log4j.properties file).
-->
<!-- Leave the listener commented-out if using JBoss -->

<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>


<!--
- Loads the root application context of this web app at startup,
- by default from "/WEB-INF/applicationContext.xml".
- Note that you need to fall back to Spring's ContextLoaderServlet for
- J2EE servers that do not follow the Servlet 2.4 initialization order.
-
- Use WebApplicationContextUtils.getWebApplicationContex t(servletContext)
- to access it anywhere in the web application, outside of the framework.
-
- The root context is the parent of all servlet-specific contexts.
- This means that its beans are automatically available in these child contexts,
- both for getBean(name) calls and (external) bean references.
-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListe ner</listener-class>
</listener>

<!--
- Spring web MVC servlet that dispatches requests to registered handlers.
- Has its own application context, by default defined in "{servlet-name}-servlet.xml",
- i.e. "petstore-servlet.xml" in this case.
-
- A web app can contain any number of such servlets.
- Note that this web app has a shared root application context, serving as parent
- of all DispatcherServlet contexts.
-->
<servlet>
<servlet-name>nestleDataFetcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/config/web-application-config.xml</param-value>
</init-param>
<load-on-startup>11</load-on-startup>
</servlet>

<!--
- Dispatcher servlet mapping for the main web user interface.
- Either refering to "petstore" for the Spring web MVC dispatcher,
- or to "action" for the Struts dispatcher.
-
- Simply comment out the "petstore" reference in favour of "action"
- to switch from the Spring web tier to the Struts web tier.
-->
<servlet-mapping>
<servlet-name>nestleDataFetcher</servlet-name>

<url-pattern>/spring/*</url-pattern>
</servlet-mapping>

<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<error-page>
<error-code>404</error-code>
<location>/error.jsp</location>
</error-page>


</web-app>


Anyway some explanation of what or how the web-application-config.xml gets called from all this or the app. knows about it would help or can I just move that logic out and put it in the applicationContext.xml?

Thanks!

myqyl4
Jan 15th, 2009, 10:27 PM
web-application-config.xml is the default DispatcherServlet Configuration file.

e.g if you DispatcherServlet is named nestleDataFetcher as shown the the web-application-config.xml should be named nestleDataFetcher-servlet.xml
If you do this and you place it under WEB-INF dir the DispatcherServlet will auto pick it up because of the matching name.

You web.xml config would then look like

<servlet>
<servlet-name>nestleDataFetcher </servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>admin</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>


<listener>
<listener-class>org.springframework.web.context.ContextLoaderListe ner</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
</param-value>
</context-param>


If you however name it something different from what your DispatcherServlet

then you would reference it the the Dispatcher Configuration as you have it



e.g.

<servlet>
<servlet-name>nestleDataFetcher </servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/some-name-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

minalecs
Jan 27th, 2009, 07:25 AM
I think I read through every post, and still no luck for me..

my web.xml


<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>

<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/classes/log4j.xml</param-value>
</context-param>
<context-param>
<param-name>flex.class.path</param-name>
<param-value>/WEB-INF/flex/hotfixes</param-value>
</context-param>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>
org.springframework.web.filter.DelegatingFilterPro xy
</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListe ner
</listener-class>
</listener>
<listener>
<listener-class>flex.messaging.HttpFlexSession</listener-class>
</listener>

<!-- The front controller of this Spring Web application, responsible for handling all application requests -->
<servlet>
<servlet-name>webapp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>webapp</servlet-name>
<url-pattern>/spring/*</url-pattern>
</servlet-mapping>

my webapp-servlet.xml


<!-- Bootstraps and exposes the BlazeDS MessageBroker -->
<bean id="managedMessageBroker" class="org.springframework.flex.messaging.MessageBrokerFa ctoryBean" />

<!-- Maps request paths at /* to the BlazeDS MessageBroker -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlH andlerMapping">
<property name="mappings">
<value>
/*=managedMessageBroker
</value>
</property>
</bean>

<!-- Dispatches requests mapped to a MessageBroker -->
<bean class="org.springframework.flex.messaging.servlet.Message BrokerHandlerAdapter"/>

<bean id="firstFlexService" class="org.springframework.flex.messaging.remoting.FlexRe motingServiceExporter">
<property name="messageBroker" ref="managedMessageBroker"/>
<property name="service" ref="firstService"/>
</bean>
<bean id="secondFlexService" class="org.springframework.flex.messaging.remoting.FlexRe motingServiceExporter">
<property name="messageBroker" ref="managedMessageBroker"/>
<property name="service" ref="secondService"/>
</bean>


In application-config.xml
just import by wild card other bean defenition files.

services-config.xml


<channels>

<channel-definition id="channel-amf" class="mx.messaging.channels.AMFChannel">
<endpoint url="http://{server.name}:{server.port}/{context.root}/spring/messagebroker/amf"
class="flex.messaging.endpoints.AMFEndpoint"/>
</channel-definition>

<channel-definition id="secure-amf" class="mx.messaging.channels.SecureAMFChannel">
<endpoint url="https://{server.name}:{server.port}/{context.root}/spring/messagebroker/amfsecure"
class="flex.messaging.endpoints.SecureAMFEndpoint"/>
<properties>
<add-no-cache-headers>false</add-no-cache-headers>
</properties>
</channel-definition>

<channel-definition id="polling-amf" class="mx.messaging.channels.AMFChannel">
<endpoint url="http://{server.name}:{server.port}/{context.root}/spring/messagebroker/amfpolling"
class="flex.messaging.endpoints.AMFEndpoint"/>
<properties>
<polling-enabled>true</polling-enabled>
<polling-interval-seconds>4</polling-interval-seconds>
</properties>
</channel-definition>
</channels>


for destination I'm referring to this - firstFlexService ..
Any help is much appreciated, as the SpringFactory solution was working. Thanks

jeremyg484
Jan 27th, 2009, 09:06 AM
Do you have a default channel configured?

minalecs
Jan 27th, 2009, 11:25 AM
hi jeremy
remoting-config.xml


<adapters>
<adapter-definition id="java-object"
class="flex.messaging.services.remoting.adapters.JavaAdap ter"
default="true" />
</adapters>

<default-channels>
<channel ref="channel-amf" />
</default-channels>


I've run out of ideas, on what else I could be doing.
code : InvokeFailed, message : [MessagingError message='Destination 'firstFlexService' either does not exist or the destination has no channels defined (and the application does not define any default channels.)']

jeremyg484
Jan 27th, 2009, 01:42 PM
And do you have the default channel set in your services-config as well? For example:



<services>

<service-include file-path="remoting-config.xml" />
<service-include file-path="proxy-config.xml" />
<service-include file-path="messaging-config.xml" />

<default-channels>
<channel ref="my-amf"/>
</default-channels>

</services>

minalecs
Jan 28th, 2009, 03:59 AM
thanks jeremy
I was missing that, also I didn't realize that the spring-springmvc with 2.5.6 release, was required, but is obvious now. overall pretty awesome.

dirk.eismann
Jan 28th, 2009, 07:26 AM
Hi Jeremy,


And do you have the default channel set in your services-config as well? For example:



<services>

<service-include file-path="remoting-config.xml" />
<service-include file-path="proxy-config.xml" />
<service-include file-path="messaging-config.xml" />

<default-channels>
<channel ref="my-amf"/>
</default-channels>

</services>


I also stumbled over this.

This should really be documented as it is for sure something that you don't have to do when using BlazeDS directly. Actually, it looks like a hack to me.

Do you mind explaining why this is needed?

Thanks,
Dirk.

jeremyg484
Jan 28th, 2009, 08:28 AM
Basically, when using dynamic destinations with BlazeDS (which is what we're doing under the hood), if you don't have an application-wide default channel in services-config, then you have to explicitly set the channel on the RemoteObject on the ActionScript/MXML side.

More details here:
http://livedocs.adobe.com/blazeds/1/blazeds_devguide/help.html?content=runtimeconfig_5.html#194376

I agree we need to make a more explicit point of this in our own docs (beyond just doing it that way in the samples) as this has come up in several threads now.

dirk.eismann
Jan 28th, 2009, 08:32 AM
hey - thanks for the info!

Dirk.

rahulhinge
Mar 22nd, 2009, 08:14 PM
Hi jeremy,

Thanks a lot for this tricky part of configuration. I struggled a lot to get Spring+BlazeDS working with flex client.
I also suggest that, we should make a explicit note for this configuration.

Thanks and Regards,
Rahul

afokado
May 10th, 2009, 05:51 PM
I also get a similar problem, though it seems with a different root cause. I define my workflowAuditService remoting service with:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:flex="http://www.springframework.org/schema/flex"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd
http://www.springframework.org/schema/flex http://www.springframework.org/schema/flex/spring-flex-1.0.xsd">

<bean id="myConfigProcessor" class="com.example.MyDestinationCountingConfigProcessor" />

<flex:message-broker>
<flex:config-processor ref="myConfigProcessor" />
</flex:message-broker>

<bean name="workflowAuditService" class="miniEos.WorkflowAuditService">
<flex:remoting-destination channels="my-amf"/>
</bean>

</beans>


my services-config.xml:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:flex="http://www.springframework.org/schema/flex"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd
http://www.springframework.org/schema/flex http://www.springframework.org/schema/flex/spring-flex-1.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">

<bean id="myConfigProcessor" class="com.example.MyDestinationCountingConfigProcessor" />

<flex:message-broker>
<flex:config-processor ref="myConfigProcessor" />
</flex:message-broker>

<bean name="workflowAuditService" class="miniEos.WorkflowAuditService">
<flex:remoting-destination channels="my-amf"/>
</bean>

<bean name="workflowService" class="miniEos.WorkflowService"/>

</beans>


and the error I get on the client side:


[RPC Fault faultString="[MessagingError message='Destination 'workflowAuditService' either does not exist or the destination has no channels defined (and the application does not define any default channels.)']" faultCode="InvokeFailed" faultDetail="Couldn't establish a connection to 'workflowAuditService'"]


I've also added the MyDestinationCountingConfigProcessor as in http://static.springframework.org/spring-flex/docs/1.0.x/reference/html/ch02s06.html, and that also shows 0 destinations... What else is needed to wire the workflowAuditService Remote Destination in?

jeremyg484
May 10th, 2009, 06:41 PM
That example is actually somewhat misleading...the destinations added by Spring won't be there yet when the ConfigProcessor runs.

If you've got the logging turned up to "info", you should see a log message showing whether the destination was registered successfully.

I would suspect the problem is that you need to define a ChannelSet on the client side.

afokado
May 11th, 2009, 03:43 AM
Yes, I can now see the following log at the server side:


2009-05-11 09:39:22,393 INFO [org.springframework.flex.remoting.RemotingDestinat ionExporter] Created remoting destination with id 'workflowAuditService'
2009-05-11 09:39:22,395 INFO [org.springframework.flex.remoting.RemotingDestinat ionExporter] Remoting destination 'workflowAuditService' has been started started successfully.


However, I'm struggling to add the ChannelSet in the client. I've attempted the following, but that gets me the same error about the destination not existing or having defined no default channels:


<mx:RemoteObject id="was" destination="workflowAuditService">
<mx:ChannelSet>
<mx:AMFChannel id="myAmf" uri="http://localhost:8088/eos2/messagebroker/amf"/>
</mx:ChannelSet>
</mx:RemoteObject>


I'm guessing the http://localhost:8088/eos2/messagebroker/amf uri is correct, as it at least gets some response (albeit an empty one) when I point my browser to it.

jeremyg484
May 11th, 2009, 06:53 AM
Need to see your services-config.xml to know what's going on here.

afokado
May 11th, 2009, 07:34 AM
Here it is, it's been copied from an example:



<?xml version="1.0" encoding="UTF-8"?>
<services-config>

<services>
<!--
<service-include file-path="remoting-config.xml" />
-->
<service-include file-path="proxy-config.xml" />
<service-include file-path="messaging-config.xml" />

<default-channels>
<channel ref="my-amf"/>
</default-channels>
</services>

<security>
<login-command class="flex.messaging.security.TomcatLoginCommand" server="Tomcat"/>
<!-- Uncomment the correct app server
<login-command class="flex.messaging.security.TomcatLoginCommand" server="JBoss">
<login-command class="flex.messaging.security.JRunLoginCommand" server="JRun"/>
<login-command class="flex.messaging.security.WeblogicLoginCommand" server="Weblogic"/>
<login-command class="flex.messaging.security.WebSphereLoginCommand" server="WebSphere"/>
-->

<!--
<security-constraint id="basic-read-access">
<auth-method>Basic</auth-method>
<roles>
<role>guests</role>
<role>accountants</role>
<role>employees</role>
<role>managers</role>
</roles>
</security-constraint>
-->
</security>

<channels>

<channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
<endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/>
</channel-definition>

<channel-definition id="my-secure-amf" class="mx.messaging.channels.SecureAMFChannel">
<endpoint url="https://{server.name}:{server.port}/{context.root}/messagebroker/amfsecure" class="flex.messaging.endpoints.SecureAMFEndpoint"/>
<properties>
<add-no-cache-headers>false</add-no-cache-headers>
</properties>
</channel-definition>

<channel-definition id="my-polling-amf" class="mx.messaging.channels.AMFChannel">
<endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amfpolling" class="flex.messaging.endpoints.AMFEndpoint"/>
<properties>
<polling-enabled>true</polling-enabled>
<polling-interval-seconds>4</polling-interval-seconds>
</properties>
</channel-definition>

<!--
<channel-definition id="my-http" class="mx.messaging.channels.HTTPChannel">
<endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/http" class="flex.messaging.endpoints.HTTPEndpoint"/>
</channel-definition>

<channel-definition id="my-secure-http" class="mx.messaging.channels.SecureHTTPChannel">
<endpoint url="https://{server.name}:{server.port}/{context.root}/messagebroker/httpsecure" class="flex.messaging.endpoints.SecureHTTPEndpoint"/>
<properties>
<add-no-cache-headers>false</add-no-cache-headers>
</properties>
</channel-definition>
-->
</channels>

<logging>
<target class="flex.messaging.log.ConsoleTarget" level="Error">
<properties>
<prefix>[BlazeDS] </prefix>
<includeDate>false</includeDate>
<includeTime>false</includeTime>
<includeLevel>false</includeLevel>
<includeCategory>false</includeCategory>
</properties>
<filters>
<pattern>Endpoint.*</pattern>
<pattern>Service.*</pattern>
<pattern>Configuration</pattern>
</filters>
</target>
</logging>

<system>
<redeploy>
<enabled>false</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/proxy-config.xml</watch-file>
<watch-file>{context.root}/WEB-INF/flex/remoting-config.xml</watch-file>
<watch-file>{context.root}/WEB-INF/flex/messaging-config.xml</watch-file>
<watch-file>{context.root}/WEB-INF/flex/data-management-config.xml</watch-file>
<touch-file>{context.root}/WEB-INF/web.xml</touch-file>
-->
</redeploy>
</system>

<!--added as part of spring integration -->
<!--
<factories>
<factory id="spring" class="flex.SpringFactory"/>
</factories>
-->
<!--added as part of spring integration -->

</services-config>

jeremyg484
May 11th, 2009, 08:04 AM
Ok, that looks good...how about your web.xml?

afokado
May 11th, 2009, 08:13 AM
pretty much standard web.xml:


<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<servlet>
<servlet-name>eos</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:applicationContext.xml
classpath:eos-servlet.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>eos</servlet-name>
<url-pattern>*.eos</url-pattern>
</servlet-mapping>

<servlet-mapping>
<servlet-name>eos</servlet-name>
<url-pattern>/messagebroker/*</url-pattern>
</servlet-mapping>

<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>


<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<el-ignored>false</el-ignored>
<page-encoding>ISO-8859-1</page-encoding>
</jsp-property-group>
</jsp-config>

<session-config>
<session-timeout>120</session-timeout>
</session-config>

</web-app>

jeremyg484
May 11th, 2009, 08:37 AM
I'm a bit stumped as this all looks right to me. The only thing I'd question at this point is the URL you are using client-side. 8088 is not the standard port, but I assume you're aware of that and have your server set up differently. If you are using the correct URL and have the logging level at info, you should see a message such as this server-side:

May 11, 2009 8:49:31 AM org.springframework.flex.servlet.MessageBrokerHand lerAdapter handle
INFO: Channel endpoint my-amf received request.

afokado
May 11th, 2009, 08:51 AM
Jeremy,

Would you be interested in a standalone test case? I could package up the server as a maven project (with all the libraries included), the client as a Flex project.

jeremyg484
May 11th, 2009, 09:13 AM
Sure, that sounds good.

afokado
May 11th, 2009, 06:18 PM
Jeremy,

I won't post the entire projects just yet. In the process of reducing the Jetty configuration to something sendable, I've managed to get rid off the problem... and cannot bring it back. I wonder how much browser caching has to do with that. I forged on and subsequently got stuck on message processing. My aim to is generate async messages by both Flex and Java (JSP) UIs, process them in Java and push out the replies to Flex. So far my approach has been:
applicationContext.xml


<flex:message-destination id="eos-input" channels="my-amf" service-adapter="messagingAdapter"/>
<flex:message-destination id="eos-output" channels="my-polling-amf"/>

<bean id="messageTemplate" class="org.springframework.flex.messaging.MessageTemplate" />

<bean name="workflowService" class="miniEos.WorkflowService"
p:messageTemplate-ref="messageTemplate"/>

<bean id="messagingAdapter" class="org.springframework.flex.core.ManageableComponentF actoryBean">
<constructor-arg value="miniEos.MyMessagingAdapter"/>
</bean>



From Java's side, I push out the messages onto the "eos-output" destination via the MessageTemplate:


ASObject aso = new ASObject();
aso.put("chatMessage", fullMessage);
template.send("eos-output", aso);


On the Flex side, I attempt to capture those messages via:


<mx:Script>
<![CDATA[
import mx.controls.DateField;
import mx.messaging.events.MessageEvent;
import mx.messaging.messages.AsyncMessage;

private function messageHandler(event:MessageEvent):void
{
log.text += event.message.body.chatMessage + "\n";
}

]]>
</mx:Script>

<mx:Consumer id="consumer" destination="eos-output" message="messageHandler(event)"/>


But they never seem to rich the Consumer... Any ideas? Additionally, is there a better approach? Also for the handling of the messages on the Java side, the messagingAdapter bean is created with a constructor hence cannot have anything wired in. In the reference guide I've seen mentions of <flex:integration-message-destination>, but could not find a working example that has Spring config, Flex and Java code. If this is the way to go - can you point me in the direction of a full example?

Many thanks,
Konrad

jeremyg484
May 12th, 2009, 06:46 AM
<bean id="messagingAdapter" class="org.springframework.flex.core.ManageableComponentF actoryBean">
<constructor-arg value="miniEos.MyMessagingAdapter"/>
</bean>




I'm unclear as to why you are trying to use a custom adapter. From what you've described, it doesn't seem necessary.





ASObject aso = new ASObject();
aso.put("chatMessage", fullMessage);
template.send("eos-output", aso);



Why are you instantiating ASObject? You should just be able to say:


template.send("eos-output", fullMessage);






<mx:Consumer id="consumer" destination="eos-output" message="messageHandler(event)"/>


But they never seem to rich the Consumer... Any ideas?


Are you calling consumer.subscribe()? And are you setting the ChannelSet for the consumer? (Same requirements here as with remoting destinations.)



Also for the handling of the messages on the Java side, the messagingAdapter bean is created with a constructor hence cannot have anything wired in.


The intention is that if you need to do custom wiring that goes beyond setting configuration properties, you extend ManageableComponentFactoryBean.

So are you then trying to use a custom adapter to handle the incoming messages? If so, then yes, it seems like using Spring Integration would be the preferred approach here. We've got an SI sample that's been floating around the team...I'll see if we can get it up online sometime today.

afokado
May 12th, 2009, 10:49 AM
Jeremy,

I admit the code is a bit all over the place, this is due to me trying to glue few examples together. I would very much appreciate your end-to-end messaging example, I'm sure it'd clear many things up.

In reference to some of your questions:
- I do call consumer.subscribe() at the application creationComplete level
- my template usage together with ASObject was to create a similar object as that fed in by Flex. I figured maybe the java message fails to be translated silently by Flex Consumer, but as a matter of fact, I don't think it ever gets there.

As far as the other questions, I can only blame on stumbling in the dark due to my lack of experience, which is where your example would hopefully show me the way.

Regards,
Konrad

jeremyg484
May 12th, 2009, 10:56 AM
Have you by chance seen Christophe Coenraets' updated RC1 test drive? I haven't posted an announcement about it here yet because he's actually still tweaking a couple of things, but it already has some good messaging examples:

http://coenraets.org/blog/2009/05/new-update-to-the-spring-blazeds-integration-test-drive/

afokado
May 13th, 2009, 09:45 AM
Jeremy,

Thanks for those examples, they did get me going, what I was missing was a proper ChannelSet declaration. But let me ask the following:


For the following code, Producer was auto-magically picking up the channels, and hence working correctly, the Consumer was not - why? Ie. the previous code:


<mx:Producer id="producer" destination="eos-input"/>
<mx:Consumer id="consumer" destination="eos-output" message="messageHandler(event)"/>


Adding channelSet="{cs}" to the Consumer fixed the problem, and had no effect on the Producer.

In my services-config.xml, I define channels as:


<channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
<endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/>
</channel-definition>

<channel-definition id="my-polling-amf" class="mx.messaging.channels.AMFChannel">
<endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amfpolling" class="flex.messaging.endpoints.AMFEndpoint"/>
<properties>
<polling-enabled>true</polling-enabled>
<polling-interval-seconds>4</polling-interval-seconds>
</properties>
</channel-definition>


in my Spring config, I define the destinations as following:


<flex:message-destination id="eos-output" channels="my-polling-amf"/>


and the way I accessed the channel from the Consumer was:


<mx:ChannelSet id="cs">
<mx:AMFChannel url="/eos2/messagebroker/amf"/>
</mx:ChannelSet>

<mx:Consumer id="consumer" destination="eos-output" message="messageHandler(event)" channelSet="{cs}"/>


This works, but what baffles me is why are coming through given that I define the eos-output destination to work with amfpolling on the server, and amf on the client... Fixing this so that they both use amfpolling has no side effect.



Cheers,
Konrad

afokado
May 13th, 2009, 10:25 AM
And 1 more thing - in the test drive examples I've not seen an alternative to initialization of the server side message listeners/consumers via any other means but ManageableComponentFactoryBean. This method is not attractive to me as the created bean is not wired up via Spring and hence, has no access to other services. Are there alternatives to that approach?

K

jeremyg484
May 13th, 2009, 10:39 AM
I would guess that you've got "my-amf" set as an application-wide default in services-config.xml, and that's why the Producer doesn't need the channel explicitly specified.

The second situation is a little more baffling. I would suspect that BlazeDS is internally falling back to the application-wide default "my-amf" after first trying "my-polling-amf" and not being able to sucessfully send, but that's just my guess without digging too much.

Have you read this part of the BlazeDS docs? May provide some more guidance:
http://livedocs.adobe.com/blazeds/1/blazeds_devguide/lcconfig_4.html#1196763

jeremyg484
May 13th, 2009, 10:44 AM
Are there alternatives to that approach?


Yes, ManageableComponentFactoryBean is not really intended for that. If you want to have Spring-managed POJOs handling incoming messages without involving JMS, the cleanest way to do this is to use a <flex:integration-message-destination> and the associated Spring Integration APIs. We will be adding a Spring Integration sample in a new version of the test drive which will be published tomorrow as part of the RC2 release.

afokado
May 14th, 2009, 02:48 AM
Interesting, in my services-config.xml I did indeed have:


<default-channels>
<channel ref="my-amf"/>
</default-channels>


Which explains why the Producer was able to communicate on it without specifying the channels. Switching the above config to "my-polling-amf" would allow the Consumer to work without specifying the channels. However, having both "my-amf" and "my-polling-amf" would only auto wire up top listed channel, ie. in the following case, the Consumer would not need to specify the its "my-polling-amf" channel, but Producer be forced to specify its "amf" one.


<default-channels>
<channel ref="my-polling-amf"/>
<channel ref="my-amf"/>
</default-channels>


Should I always define the channels on the client side...? It'd be nice for the server to control which channels it broadcasts on.

And thanks, looking forward to the <flex:integration-message-destination> examples in test drive RC2.

Regards,
Konrad

afokado
May 22nd, 2009, 01:09 PM
Jeremy,

Sorry for being inactive recently. I've looked at RC2 and cannot see the <flex:integration-message-destination> example - can you direct me where to look?

Many thanks,
Konrad

jeremyg484
May 22nd, 2009, 01:14 PM
It is referred to in the walk-through as the "POJO Messaging" sample. In the sample file structure it is under "spring-messaging".

FYI, I think Mark Fisher (Spring Integration lead) has plans to add a couple more Spring Integration samples for 1.0 final as well.