/*************************************************************************
*
* ADOBE CONFIDENTIAL
* __________________
*
* [2002] - [2007] Adobe Systems Incorporated
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of Adobe Systems Incorporated and its suppliers,
* if any. The intellectual and technical concepts contained
* herein are proprietary to Adobe Systems Incorporated
* and its suppliers and may be covered by U.S. and Foreign Patents,
* patents in process, and are protected by trade secret or copyright law.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe Systems Incorporated.
*/
package features.bootstrapservices;
import java.util.Hashtable;
import flex.messaging.MessageDestination;
import flex.messaging.config.ConfigMap;
import flex.messaging.config.NetworkSettings;
import flex.messaging.config.ServerSettings;
import flex.messaging.config.ThrottleSettings;
import flex.messaging.config.ThrottleSettings.Policy;
import flex.messaging.services.AbstractBootstrapService;
import flex.messaging.services.Service;
import flex.messaging.services.messaging.adapters.JMSAdapter;
import flex.messaging.services.messaging.adapters.JMSSettings;
/**
* This BootstrapService is used to dynamicaly create a Messaging Service along
* with its Messaging Destinations without the need for any configuration files.
*/
public class MessagingBootstrapService extends AbstractBootstrapService
{
/**
* Called by the <code>MessageBroker</code> after all of the server
* components are created but right before they are started. This is
* usually the place to create dynamic components.
*
* @param id Id of the <code>AbstractBootstrapService</code>.
* @param properties Properties for the <code>AbstractBootstrapService</code>.
*/
public void initialize(String id, ConfigMap properties)
{
Service messagingService = createService();
createDestination1(messagingService);
createDestination2(messagingService);
}
/**
* Called by the <code>MessageBroker</code> as server starts. Useful for
* custom code that needs to run after all the components are initialized
* and the server is starting up.
*/
public void start()
{
// No-op.
}
/**
* Called by the <code>MessageBroker</code> as server stops. Useful for
* custom code that needs to run as the server is shutting down.
*/
public void stop()
{
// No-op.
}
/*
<?xml version="1.0" encoding="UTF-8"?>
<service id="message-service" class="flex.messaging.services.MessageService">
<!-- Example messaging-config.xml -->
<adapters>
<!--
id: a unique id specifying the adapter
class: the Flex Enterprise class which implements the adapter
possible values: flex.messaging.services.messaging.adapters.ActionScriptAdapter
flex.messaging.services.messaging.adapters.JMSAdapter
coldfusion.flex.CFEventGatewayAdapter
default: an optional attribute identifying the adapter to use when none is specified
-->
<adapter-definition id="actionscript" class="flex.messaging.services.messaging.adapters.ActionScriptAdapter" default="true" />
<adapter-definition id="jms" class="flex.messaging.services.messaging.adapters.JMSAdapter"/>
</adapters>
*/
private Service createService()
{
String serviceId = "messaging-service";
String serviceClass = "flex.messaging.services.MessageService";
Service messageService = broker.createService(serviceId, serviceClass);
messageService.registerAdapter("actionscript", "flex.messaging.services.messaging.adapters.ActionScriptAdapter");
messageService.registerAdapter("jms", "flex.messaging.services.messaging.adapters.JMSAdapter");
messageService.setDefaultAdapter("actionscript");
return messageService;
}
/*
<!-- Example ActionScriptAdapter destination -->
<destination id="MyTopic">
<properties>
<network>
<!--
Idle time in minutes for a subscriber to receive no messages
that triggers it to be automatically unsubscribed.
0 means don't force subscribers to unsubscribe automatically.
Default value is 0.
-->
<subscription-timeout-minutes>0</subscription-timeout-minutes>
<!--
Throttling can be set up destination-wide as well as per-client.
The inbound policy may be NONE, ERROR or IGNORE and the outbound policy may be NONE and IGNORE.
All throttle frequency values are considered the maximum allowed messages per second.
A frequency of 0 disables throttling altogether.
-->
<throttle-inbound policy="ERROR" max-frequency="0"/>
<throttle-outbound policy="IGNORE" max-frequency="0"/>
</network>
<server>
<!-- Max number of messages to maintain in memory cache -->
<max-cache-size>1000</max-cache-size>
<!-- message-time-to-live of 0 means live forever -->
<message-time-to-live>0</message-time-to-live>
<!--
The subtopic feature lets you divide the messages that a Producer component sends to a destination
into specific categories at the destination. You can configure a Consumer component that subscribes to
the destination to receive only messages sent to a specific subtopic or set of subtopics. You use
wildcard characters (*) to send or receive messages from more than one subtopic. The subtopic-separator
element is optional; the default value is period
-->
<allow-subtopics>true</allow-subtopics>
<subtopic-separator>.</subtopic-separator>
<!--
Used to choose the algorithm for routing messages in a cluster.
When set to server-to-server (the default), subscriptions are
broadcast through the cluster to ensure each server knows which
destinations, subtopics, and selector expressions define subscriptions
for clients connected to other servers. When a data message
arrives, it is then only sent to servers who have clients interested
in that message. The other value for this setting "broadcast"
will simply broadcast all data messages to all servers. In this
mode, subscribe/unsubscribe messages are not sent across the cluster
-->
<cluster-message-routing>server-to-server</cluster-message-routing>
</server>
</properties>
<channels>
<!--
Set the ref id of the default channels to use as transport for this service.
The channel is defined elsewhere using the channel-definition tag.
-->
<channel ref="my-polling-amf"/>
</channels>
</destination>
*/
private void createDestination1(Service service)
{
String destinationId = "MyTopic";
MessageDestination destination = (MessageDestination)service.createDestination(destinationId);
NetworkSettings ns = new NetworkSettings();
ns.setSubscriptionTimeoutMinutes(0);
ThrottleSettings ts = new ThrottleSettings();
ts.setInboundPolicy(Policy.ERROR);
ts.setIncomingDestinationFrequency(0);
ts.setOutboundPolicy(Policy.IGNORE);
ts.setOutgoingDestinationFrequency(0);
ns.setThrottleSettings(ts);
destination.setNetworkSettings(ns);
ServerSettings ss = new ServerSettings();
ss.setMessageTTL(0);
ss.setBroadcastRoutingMode("server-to-server");
destination.setServerSettings(ss);
destination.addChannel("my-polling-amf");
}
/*
<!-- Example JMSAdapter destination -->
<destination id="MyJMSTopic">
<properties>
<server>
<!-- Optional. Default is false. This option is currently only used by JMS
adapter when the destination-type is Topic. In that case, durable JMS
consumers will be used by the JMS adapter. Note that this does not
guarantee durability between Flex clients and JMS adapter but rather
between JMS adapter and JMS server.
<durable>false</durable>
</server>
<!-- For specifics on JMS, please reference the Java Message Service specification or your J2EE server documentation -->
<jms>
<!--
This determines whether the adapter is performing topic (pub/sub) or queue (point-to-point) messaging.
This element is optional and defaults to Topic.
<destination-type>Topic</destination-type>
-->
<!--
The name of the destination in JMS
This element is optional and defaults to the destination id
<destination-name>FlexTopic</destination-name>
-->
<!--
The javax.jms.Message type which the adapter should use for this destination.
Supported types: javax.jms.TextMessage, javax.jms.ObjectMessage
-->
<message-type>javax.jms.TextMessage</message-type>
<!-- The name of the JMS connection factory in JNDI -->
<connection-factory>jms/flex/TopicConnectionFactory</connection-factory>
<!-- The name of the destination in JNDI -->
<destination-jndi-name>jms/topic/flex/simpletopic</destination-jndi-name>
<!-- The JMS DeliveryMode for producers -->
<delivery-mode>NON_PERSISTENT</delivery-mode>
<!-- The JMS priority for messages sent by Flash producers -->
<message-priority>DEFAULT_PRIORITY</message-priority>
<!--
The message acknowledgement mode for the JMS adapter
None of these modes require any action on the part of the Flex messaging client.
Supported modes:
AUTO_ACKNOWLEDGE - the JMS provider client runtime automatically acknowledges the messages
DUPS_OK_ACKNOWLEDGE - auto-acknowledgement of the messages is not required
CLIENT_ACKNOWLEDGE - the JMS adapter should acknowledge that the message was received
-->
<acknowledge-mode>AUTO_ACKNOWLEDGE</acknowledge-mode>
<!-- The JMS session transaction mode -->
<transacted-sessions>false</transacted-sessions>
<!--
The maximum number of producer proxies that this destination
should use when communicating with the JMS Server. The default
is 1 which implies all clients using this destinatin will
share the same connection to the JMS server.
-->
<max-producers>1</max-producers>
<!-- (Optional) JNDI environment. Use when using JMS on a remote JNDI server.
Used to specify the JNDI environment to access an external JMS provider.
-->
<initial-context-environment>
<property>
<name>Context.SECURITY_PRINCIPAL</name>
<value>anonymous</value>
</property>
<property>
<name>Context.SECURITY_CREDENTIALS</name>
<value>anonymous</value>
</property>
<property>
<name>Context.PROVIDER_URL</name>
<value>http://{server.name}:1856</value>
</property>
<property>
<name>Context.INITIAL_CONTEXT_FACTORY</name>
<value>fiorano.jms.runtime.naming.FioranoInitialContextFactory</value>
</property>
</initial-context-environment>
</jms>
</properties>
<channels>
<channel ref="my-polling-amf"/>
</channels>
<security>
<security-constraint ref="sample-users"/>
</security>
<adapter ref="jms"/>
</destination>
*/
private void createDestination2(Service service)
{
String destinationId = "MyJMSTopic";
MessageDestination destination = (MessageDestination)service.createDestination(destinationId);
ServerSettings ss = new ServerSettings();
ss.setDurable(false);
destination.setServerSettings(ss);
String adapterId = "jms";
JMSAdapter adapter = (JMSAdapter)destination.createAdapter(adapterId);
// JMS settings are set at the adapter level
JMSSettings jms = new JMSSettings();
jms.setDestinationType("Topic");
jms.setMessageType("javax.jms.TextMessage");
jms.setConnectionFactory("jms/flex/TopicConnectionFactory");
jms.setDestinationJNDIName("jms/topic/flex/simpletopic");
jms.setDeliveryMode("NON_PERSISTENT");
//jms.setMessagePriority(javax.jms.Message.DEFAULT_PRIORITY);
jms.setAcknowledgeMode("AUTO_ACKNOWLEDGE");
jms.setMaxProducers(1);
Hashtable envProps = new Hashtable();
envProps.put("Context.SECURITY_PRINCIPAL", "anonymous");
envProps.put("Context.SECURITY_CREDENTIALS", "anonymous");
envProps.put("Context.PROVIDER_URL", "http://{server.name}:1856");
envProps.put("Context.INITIAL_CONTEXT_FACTORY", "fiorano.jms.runtime.naming.FioranoInitialContextFactory");
jms.setInitialContextEnvironment(envProps);
adapter.setJMSSettings(jms);
destination.setSecurityConstraint("sample-users");
destination.addChannel("my-polling-amf");
}
}