Sie können die Correspondence Management Solution-APIs in der LiveCycle-Plattform (Prozess/Orchestrierung) als Teil eines größeren Workflows aufrufen.
Um einen benutzerdefinierten Dienstcontainer zu erstellen, sind die folgenden Bibliotheken erforderlich: com.springsource.org.aopalliance-1.0.0.jar
spring-aop-3.0.2.RELEASE.jar
spring-asm-3.0.2.RELEASE.jar
spring-beans-3.0.2.RELEASE.jar
spring-context-3.0.2.RELEASE.jar
spring-core-3.0.2.RELEASE.jar
spring-expression-3.0.2.RELEASE.jar
spring-security-core-3.0.2.RELEASE.jar
spring-security-web-3.0.2.RELEASE.jar
spring-web-3.0.2.RELEASE.jar
dom4j-1.6.1.jar
commons-logging-1.1.jar
adobe-acm-client.jar
adobe-dct-client.jar
lc-content-api.jar
Übersicht über die ImplementierungIn den folgenden Beispielen werden benutzerdefinierte Dienstcontainer erstellt, die Folgendes offenlegen (Dienstcontainervorgänge in der Orchestrierung): Benutzerdefinierte Dienstvorgänge, die die Correspondence Management-APIs intern nutzen
Direkte Correspondence Management-APIs/-Vorgänge
Benutzerdefinierter Dienst als ein DienstcontainervorgangSie können einen benutzerdefinierten Dienstvorgang implementieren, der die Correspondence Management-APIs verwendet, um einige Funktionen zu implementieren. Anschließend können Sie diesen Vorgang in Ihrem Dienstcontainer offenlegen. Führen Sie zu diesem Zweck die folgenden Aufgaben durch: Benutzerdefinierten Dienst erstellen
Den Dienst als Bean registrieren
Die offengelegte Eigenschaftsdatei für die Komponente erstellen
Den benutzerdefinierten Dienst als einen LiveCycle-Dienst exportieren
Dienstcontainerkomponente definieren
Benutzerdefinierten Dienst erstellenSchreiben Sie einen schnittstellenbasierten benutzerdefinierten Dienst, der die offengelegten Correspondence Management-APIs verwendet, um die erforderliche benutzerdefinierte Aufgabe zu erfüllen. Im folgenden Beispiel wird ein Dienst offengelegt, um die verarbeitete Layout-Vorlage einer Korrespondenz und die verarbeiteten XML-Daten abzurufen, sodass sie zusammengeführt werden können, um die Korrespondenz in einem benutzerdefinierten Format zu erstellen:
Die Schnittstelle „IRenderServiceWrapper.java“:
package com.adobe.livecycle.cmsa;
import java.util.Map;
import com.adobe.idp.Document;
public interface IRenderServiceWrapper {
public abstract Map<String, Document> getProcessedTemplate(String letterName, String initialXmlData, Boolean useTestData);
}
Die Implementierung „RenderServiceWrapper.java“:
package com.adobe.livecycle.cmsa;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.adobe.icc.dbforms.obj.Letter;
import com.adobe.icc.dbforms.obj.Query;
import com.adobe.icc.dbforms.obj.Statement;
import com.adobe.icc.dbforms.obj.Statement.Operator;
import com.adobe.icc.ddg.api.LetterRenderService;
import com.adobe.icc.services.api.LetterService;
import com.adobe.idp.Document;
public class RenderServiceWrapper implements IRenderServiceWrapper {
private LetterRenderService renderService;
private LetterService letterService;
/**
* {@inheritDoc}
*/
public Map<String, Document> getProcessedTemplate(String letterName, String initialXmlData, Boolean useTestData)
{
Map<String, Document> result = new HashMap<String, Document>();
if (letterName != null && !"".equals(letterName))
{
Statement st = new Statement();
st.setAttributeName("name");
st.setOperator(Operator.EQUALS);
st.setAttributeValue(letterName);
Query query = new Query();
query.setObjectType(Letter.class.getSimpleName());
query.addStatement(st);
List<Letter> letters = letterService.getAllLetters(query);
if (letters.size() > 0)
{
Map<String, Object> processedData = renderService.processLetter(letters.get(0).getId(), initialXmlData, useTestData);
Document xdp = new Document((byte[])processedData.get(LetterRenderService.LAYOUT_TEMPLATE_KEY));
Document xml = new Document((byte[])processedData.get(LetterRenderService.XML_DATA_KEY));
result.put(LetterRenderService.LAYOUT_TEMPLATE_KEY, xdp);
result.put(LetterRenderService.XML_DATA_KEY, xml);
}
else
System.out.println("No Letter found with name : " + letterName);
}
else
System.out.println("No Letter name provided.");
return result;
}
public LetterRenderService getRenderService() {
return renderService;
}
public void setRenderService(LetterRenderService renderService) {
this.renderService = renderService;
}
public LetterService getLetterService() {
return letterService;
}
public void setLetterService(LetterService letterService) {
this.letterService = letterService;
}
}
Als Spring-Bean registrierenNachdem der oben genannte Dienst implementiert wurde, registrieren Sie ihn als ein Spring-Bean in Ihrem (Spring-basierten) benutzerdefinierten Dienstcontainer:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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.xsd">
<bean name="lc.remotingClientParent"
class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean"
abstract="true">
<property name="httpInvokerRequestExecutor" ref="CRXAuthHttpInvokerRequestExecutor" />
</bean>
<bean id="CRXAuthHttpInvokerRequestExecutor"
class="com.adobe.livecycle.spring.remoting.CRXAuthHttpInvokerRequestExecutor">
<property name="appRoot" value="/content/apps/cm"/>
</bean>
<bean name="LetterService" parent="lc.remotingClientParent">
<property name="serviceUrl"
value="${crx.serverUrl}/bin/remoting/lc.icc.dbservices.letterService" />
<property name="serviceInterface" value="com.adobe.icc.services.api.LetterService" />
</bean>
<bean name="LetterRenderService" parent="lc.remotingClientParent">
<property name="serviceUrl"
value="${crx.serverUrl}/bin/remoting/lc.icc.renderlib.letterRenderService" />
<property name="serviceInterface" value="com.adobe.icc.ddg.api.LetterRenderService" />
</bean>
<bean name="RenderServiceWrapper" class="com.adobe.livecycle.cmsa.RenderServiceWrapper">
<property name="renderService" ref="LetterRenderService" />
<property name="letterService" ref="LetterService" />
</bean>
<bean id="testProps"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:cmsa.properties</value>
<value>file:C:/Adobe/config/cmsa.properties</value>
</list>
</property>
</bean>
</beans>
Die offengelegte Eigenschaftsdatei für die Komponente erstellenNachstehend finden Sie ein Beispiel der standardmäßigen Eigenschaftendatei (cmsa.properties) in der Komponente im Klassenpfad: # URL to the Spring app.
crx.serverUrl=http://localhost:4502
# more propeties here>
Den benutzerdefinierten Dienst als einen LiveCycle-Dienst exportierenNachdem die Dienste als Spring-Bean verfügbar sind, können Sie sie als LiveCycle-Dienst exportieren. Definieren Sie eine com.adobe.idp.dsc.component.ServiceInstanceFactory-Implementierung (SpringServiceFactory.java) wie folgt:
package com.adobe.livecycle.spring;
import com.adobe.idp.dsc.DSCException;
import com.adobe.idp.dsc.component.ComponentContext;
import com.adobe.idp.dsc.component.support.AbstractServiceInstanceFactory;
import com.adobe.idp.dsc.registry.infomodel.ServiceConfiguration;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.access.ContextSingletonBeanFactoryLocator;
public class SpringServiceFactory extends AbstractServiceInstanceFactory {
public void activateInstance(ServiceConfiguration serviceConfiguration,
Object o) {
}
public Object createInstance(ServiceConfiguration serviceConfiguration)
throws DSCException {
return getBeanFactory(serviceConfiguration).getBean(
serviceConfiguration.getServiceId());
}
public void destroyInstance(ServiceConfiguration serviceConfiguration,
Object o) throws DSCException {
}
public void passivateInstance(ServiceConfiguration serviceConfiguration,
Object o) {
}
public boolean validateInstance(ServiceConfiguration serviceConfiguration,
Object o) {
return true;
}
private BeanFactory getBeanFactory(ServiceConfiguration serviceConfiguration) {
String componentId = serviceConfiguration.getComponentId();
ComponentContext ctx = getComponentContext();
ClassLoader cl = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(ctx.getClassLoader());
return ContextSingletonBeanFactoryLocator.getInstance(
"classpath:/spring/beanRefContext.xml").useBeanFactory(
componentId).getFactory();
} finally {
Thread.currentThread().setContextClassLoader(cl);
}
}
}
Die Factory im obigen Beispiel erwartet eine Spring-Konfigurationsdatei mit dem Namen beanRefContext.xml unter „classpath:/spring“, die die eigentliche Spring-Konfiguration/-Beans des Clients lädt. Beispiel:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
xmlns:context="http://www.springframework.org/schema/context">
<!--
Note: The beanId must be same as the componentId
-->
<bean name="com.adobe.livecycle.cmsa.RenderWrapper" class="org.springframework.context.support.ClassPathXmlApplicationContext">
<property name="configLocations">
<value>
classpath:cmsa-spring-config.xml
</value>
</property>
</bean>
</beans>
Folgen Sie folgenden Konventionen, um die Komponenten-/Dienstdefinitionen zu vereinfachen und die Beans als einen LiveCycle-Dienst offenzulegen:
Die Bean-ID oder der Bean-Name in beanRefContext.xml ist derselbe wie die Komponenten-ID, wie in der „component.xml“ des Dienstcontainers definiert.
Das benutzerdefinierte Dienst-Bean weist denselben Namen wie die LiveCycle-Dienst-ID auf, wie in der component.xml des Dienstcontainers definiert.
Dienstcontainerkomponente definierenAnschließend definieren Sie die Details der Dienstcontainerkomponente in der component.xml wie folgt:
<component xmlns="http://adobe.com/idp/dsc/component/document">
<component-id>com.adobe.livecycle.cmsa.RenderWrapper</component-id>
<version>1.0</version>
<services>
<!-- Service name must be same as the name of the corresponding Spring
bean -->
<service name="RenderServiceWrapper" orchestrateable="true">
<implementation-class>com.adobe.livecycle.cmsa.IRenderServiceWrapper
</implementation-class>
<auto-deploy service-id="RenderServiceWrapper"
minor-version="0" major-version="1" category-id="Correspondence Management" />
<operations>
<operation name="getProcessedTemplate">
<input-parameter name="letterName" title="Letter Name"
type="java.lang.String" />
<input-parameter name="initialXmlData" title="Initial XML Data (for DDI)"
type="java.lang.String" />
<input-parameter name="useTestData" title="Use Letter Test Data?"
type="java.lang.Boolean" />
<output-parameter name="result"
title="Result Map with Layout and Data" type="java.util.Map" />
</operation>
</operations>
</service>
<!-- Mandatory service to capture CRX credentials -->
<service name="CRXUserCredentialService">
<implementation-class>com.adobe.livecycle.crx.CRXUserCredentialService
</implementation-class>
<factory-method>getInstance</factory-method>
<supported-connectors></supported-connectors>
<auto-deploy major-version="1" service-id="CRXUserCredentialService"
category-id="Correspondence Management" />
<config-parameter name="username" type="java.lang.String"
title="Username">
<description>User name with which to connect to CM</description>
<default-value>admin</default-value>
</config-parameter>
<config-parameter name="password" type="java.lang.String"
title="Password">
<description>Password for the above user</description>
<default-value>admin</default-value>
<property-editor editor-id="com.adobe.idp.dsc.propertyeditor.system.PasswordPropertyEditorComponent" />
</config-parameter>
<operation-config>
<operation-name>*</operation-name>
<transaction-type>None</transaction-type>
</operation-config>
</service>
</services>
<supports-export>false</supports-export>
<class-path>lib/dom4j-1.6.1.jar lib/lc-content-api.jar lib/adobe-acm-client.jar lib/adobe-dct-client.jar lib/com.springsource.org.aopalliance-1.0.0.jar lib/spring-aop-3.0.2.RELEASE.jar lib/spring-asm-3.0.2.RELEASE.jar lib/spring-beans-3.0.2.RELEASE.jar lib/spring-context-3.0.2.RELEASE.jar lib/spring-core-3.0.2.RELEASE.jar lib/spring-expression-3.0.2.RELEASE.jar lib/spring-web-3.0.2.RELEASE.jar lib/spring-security-core-3.0.2.RELEASE.jar</class-path>
<service-factory-class>com.adobe.livecycle.spring.SpringServiceFactory
</service-factory-class>
</component>
Correspondence Management-Dienste direkt als einen Dienstcontainervorgang offenlegenSie können auch den gesamten Correspondence Management-Dienst, der bereits über HTTP-Remoting offengelegt ist, und seine Vorgänge als einen LiveCycle-Dienst offenlegen, anstatt ihn innerhalb eines benutzerdefinierten Dienstes aufzunehmen. Um beispielsweise den FormService und seine Vorgänge offenzulegen, fügen Sie einfach der component.xml die folgenden Einträgen hinzu:
<component xmlns="http://adobe.com/idp/dsc/component/document">
...
...
<services>
<!-- Again, the Service name/id must be same as the name of the corresponding Spring bean, defined in cmsa-spring-config.xml -->
<service name="FormService" orchestrateable="true">
<implementation-class>com.adobe.livecycle.cmsa.FormQueryService</implementation-class>
<auto-deploy service-id="FormService" minor-version="0" major-version="1" category-id="CMSA"/>
</service>
...
<!-- more services here -->
...
</services>
...
...
</component>
AuthentifizierungsübertragungSie können einen Aufrufkontext für CRX festlegen, sodass die Dienstcontainerkonfiguration ausgefüllt werden kann, um Correspondence Management-APIs aufzurufen. Erstellen Sie eine benutzerdefinierte Dienstkonfiguration, die einen Satz Benutzeranmeldedaten für CRX erfasst, die über Berechtigungen für Correspondence Management-Inhalt verfügen. Die folgende Definition legt die Konfigurationen auf der LiveCycle Document Services Platform-Administratorbenutzeroberfläche offen.:
<service name="CRXUserCredentialService">
<implementation-class>com.adobe.livecycle.crx.CRXUserCredentialService
</implementation-class>
<factory-method>getInstance</factory-method>
<supported-connectors></supported-connectors>
<auto-deploy major-version="1" service-id="CRXUserCredentialService"
category-id="Correspondence Management" />
<config-parameter name="username" type="java.lang.String"
title="Username">
<description>User name with which to connect to CM</description>
<default-value>admin</default-value>
</config-parameter>
<config-parameter name="password" type="java.lang.String"
title="Password">
<description>Password for the above user</description>
<default-value>admin</default-value>
<property-editor editor-id="com.adobe.idp.dsc.propertyeditor.system.PasswordPropertyEditorComponent" />
</config-parameter>
<operation-config>
<operation-name>*</operation-name>
<transaction-type>None</transaction-type>
</operation-config>
</service>
Konfiguration: Navigieren Sie zu Administratorbenutzeroberfläche > Dienste > Anwendungen und Dienste > Dienstverwaltung.
Wählen Sie Correspondence Management als Kategorie.
Wählen Sie den CRXUserCredentialService-Dienst.
Geben Sie den für die CRX-Instanz erstellten Benutzernamen und das Kennwort an, mit dem auf Correspondence Management zugegriffen werden kann.
Klicken Sie auf Speichern.
Benutzerdefinierte Authentifizierungs-AusführungsfunktionDie folgende CRXAuthHttpInvokerRequestExecutor.java-Datei ist die benutzerdefinierte Ausführungsfunktion der Authentifizierungsanforderung. Diese API überschreibt die grundlegende Ausführungsfunktion der Authentifizierungsanforderung und verwendet CRXUserCredentialService, um einen Systemkontext für API-Aufrufe zu erstellen. package com.adobe.livecycle.spring.remoting;
import java.io.IOException;
import java.net.HttpURLConnection;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.remoting.httpinvoker.AuthenticationSimpleHttpInvokerRequestExecutor;
import com.adobe.livecycle.content.appcontext.AppContextManager;
import com.adobe.livecycle.crx.CRXUserCredentialService;
public class CRXAuthHttpInvokerRequestExecutor extends
AuthenticationSimpleHttpInvokerRequestExecutor {
private String appRoot;
public String getAppRoot() {
return appRoot;
}
public void setAppRoot(String appRoot) {
this.appRoot = appRoot;
}
@Override
protected void prepareConnection(HttpURLConnection con, int contentLength)
throws IOException {
boolean clearContext = false;
try {
if (SecurityContextHolder.getContext().getAuthentication() == null) {
clearContext = true;
CRXUserCredentialService credentialService = CRXUserCredentialService
.getInstance();
UsernamePasswordAuthenticationToken ut = new UsernamePasswordAuthenticationToken(
credentialService.getUsername(),
credentialService.getPassword());
SecurityContext sctx = SecurityContextHolder
.createEmptyContext();
sctx.setAuthentication(ut);
SecurityContextHolder.setContext(sctx);
}
super.prepareConnection(con, contentLength);
con.setRequestProperty(AppContextManager.APP_CONTEXT_HEADER_NAME, appRoot);
} finally {
if (clearContext) {
SecurityContextHolder.clearContext();
}
}
}
}
|
|
|