4. Configuration for CDI
Library dependencies
In order to initialize GDS/Tide for CDI and Hibernate, you must add granite.jar, granite-hibernate.jar and granite-cdi.jar to your WEB-INF/lib or in the lib directory of an ear.
With ear packaging, it is necessary to put all libs in ear/lib and to make sure that no jar concerning JPA persistence is left in WEB-INF/lib.
Simplified configuration with Servlet 3 containers
The easiest way to add GraniteDS support to a CDI project in a Servlet 3 compliant container (currently only GlassFish v3) is by adding a configuration class in your project. This class will be scanned by the servlet 3 container and GraniteDS will use the annotation parameters to determine the application configuration :
import org.granite.config.servlet3.FlexFilter; import org.granite.gravity.config.AbstractMessagingDestination; import org.granite.gravity.config.servlet3.MessagingDestination; import org.granite.tide.cdi.CDIServiceFactory; import org.granite.tide.cdi.Identity; @FlexFilter( tide=true, type="cdi", factoryClass=CDIServiceFactory.class, tideInterfaces={Identity.class} ) public class GraniteConfig { }
The @FlexFilter declaration will setup an AMF processor for the default url mapping /graniteamf/*, and the tide attribute indicates that you want to configure a Tide-enabled service factory.
Other configurations can be done though @FlexFilter :
- tideAnnotations is equivalent to tide-component annotated-with="" in granite-config.xml. It allows to define the list of annotation names that enable remote access to CDI beans.
- tideInterfaces is equivalent to tide-component implements="" in granite-config.xml.
- tideRoles allows to define a list of security roles that are required to access the Tide remote destination. In general it is not necessary to define this destination-wide security and only rely on container security for fine-grained access to individual CDI beans.
- exceptionConverters allows to define a list of server-side exception converters. It's the equivalent to exception-converters in granite-config.xml.
- amf3MessageInterceptor allows to define a message interceptor class. It's highly recommended to subclass CDIInterceptor and call super.before and super.after in your implementation.
- securityServiceClass allows to define the security service implementation. In general it's optional because Tide will try to automatically detect a suitable implementation depending on the container.
As there is no services-config.xml in this kind of setup, you will have to define manually the endpoint for remote services. This can be done by defining a service initializer in a static block of the main mxml file :
Cdi.getInstance().addComponentWithFactory("serviceInitializer",
DefaultServiceInitializer,
{ contextRoot: "/my-cdi-app" }
);
Note that if you have choosen this kind of simplified configuration, you generally don't need to read the following sections. However if you have more specific requirements, you can still define granite-config.xml and/or services-config.xml files that will override or complete the configuration.
General Web Configuration (web.xml)
Then you have to add the following configuration to your web.xml:
<web-app version="2.4" ...> ... <!-- GDS AMF message filter --> <filter> <filter-name>AMFMessageFilter</filter-name> <filter-class>org.granite.messaging.webapp.AMFMessageFilter</filter-class> <!-- Uncomment (part of) this block if configs are not present at default locations. <init-param> <param-name>servicesConfigPath</param-name> <param-value>/WEB-INF/flex/services-config.xml</param-value> </init-param> <init-param> <param-name>graniteConfigPath</param-name> <param-value>/WEB-INF/granite/granite-config.xml</param-value> </init-param--> </filter> <filter-mapping> <filter-name>AMFMessageFilter</filter-name> <url-pattern>/graniteamf/*</url-pattern> </filter-mapping> <!-- GDS AMF Servlet --> <servlet> <servlet-name>AMFMessageServlet</servlet-name> <servlet-class>org.granite.messaging.webapp.AMFMessageServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>AMFMessageServlet</servlet-name> <url-pattern>/graniteamf/*</url-pattern> </servlet-mapping> ... </web-app>
Flex/GDS Configuration
To use Tide/CDI services in your Flex application, you have to configure a specific destination and service factory in services-config.xml:
<services-config> <services> <service id="granite-service" class="flex.messaging.services.RemotingService" messageTypes="flex.messaging.messages.RemotingMessage"> <!-- ! Use "tideCdiFactory" and "graniteamf" for "cdi" destination (see below). ! The destination must be "cdi" when using Tide with default configuration. !--> <destination id="cdi"> <channels> <channel ref="graniteamf"/> </channels> <properties> <factory>tideCdiFactory</factory> </properties> </destination> </service> </services> <!-- ! Declare tideCdiFactory service factory. !--> <factories> <factory id="tideCdiFactory" class="org.granite.tide.cdi.CDIServiceFactory" /> </factories> <!-- ! Declare graniteamf channel. !--> <channels> <channel-definition id="graniteamf" class="mx.messaging.channels.AMFChannel"> <endpoint uri="http://{server.name}:{server.port}/{context.root}/graniteamf/amf" class="flex.messaging.endpoints.AMFEndpoint"/> </channel-definition> </channels> </services-config>
Note that this is the one and only destination configuration needed for all remote component calls.
There is then a little more configuration in granite-config.xml for Tide and security integration:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE granite-config PUBLIC "-//Granite Data Services//DTD granite-config internal//EN" "http://www.graniteds.org/public/dtd/2.0.0/granite-config.dtd"> <granite-config> <amf3-message-interceptor type="org.granite.cdi.CDIInterceptor"/> <externalizers> <externalizer type="org.granite.hibernate.HibernateExternalizer"> <include annotated-with="javax.persistence.Entity"/> <include annotated-with="javax.persistence.MappedSuperclass"/> <include annotated-with="javax.persistence.Embeddable"/> </externalizer> ... </externalizers> ... <security type="org.granite.messaging.service.security.GlassFishV3SecurityService"/> <tide-components> <!-- List of component matchers, see 'Enabling components' section --> </tide-components> </granite-config>
Note that this part is much simpler if you use the automatic scanning of GraniteDS 1.1+:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE granite-config PUBLIC "-//Granite Data Services//DTD granite-config internal//EN" "http://www.graniteds.org/public/dtd/2.0.0/granite-config.dtd"> <granite-config scan="true"> <security type="org.granite.messaging.service.security.GlassFishV3SecurityService"/> <tide-components> <!-- List of component matchers, see 'Enabling components' section --> </tide-components> </granite-config>
