On Fri, May 23, 2008 at 9:03 AM, Mike Edwards < [EMAIL PROTECTED]> wrote:
> Matthieu Riou wrote: > >> What mike says. I should just add that picking the right process version >> depending on what's already executing is handled by the runtime. The only >> thing that it will need is to know what is the definition for all the >> process versions that are still around (haven't been undeployed). You just >> need to keep these artifacts around and feed them to the engine (by >> calling >> register) as long as they're needed. >> >> If you want, I can code the method that compiles the BPEL file if you give >> me a signature that gets the file as parameter (I don't know how you would >> look it up in the filesystem). >> >> Cheers, >> Matthieu >> >> >> >>> Yours optimistically, >>> >>> Mike. >>> >>> Matthieu, > > I'd appreciate it if you could pass your eyes over my implementation of a > ProcessConf, inline below. > > There are a few questions that I have: > > 1) ProcessConfImpl from the ODE code has more public methods than are > present in the ProcessConf interface. What are they used for - and by which > code? > Those are only used by the store implementation or by a test case for one of them. You don't need to worry about those as you won't have a store implementation. > > 2) What is getDefinitionforService(...) supposed to return? The problem is > over the interpretation of the name "Service" - what kind of service is > this? A service from the WSDL? A service as listed in the deploy.xml file? > And what definition are we talking about - the definition of the Service in > the WSDL file, or the definition of the portType at which the service > points? > It returns the WSDL object model associated with a given WSDL service qualified name. When something gets deployed, we scan all the WSDL documents and associate them with the services they define. This method is basically used by the engine to get the definition of the services that you defined in the deploy.xml. It can then pass this definition on to the integration layer when it wants a service to get activated. > > 3) What are Properties as returned by getProperties()? > We have a set of custom name/value properties that can be defined in the deploy.xml that people can use to attribute some custom values to their process definitions. This is mostly used in the management API so that a graphical tool listing all process definitions could for example filter them by department. Those are somewhat different to what SCA properties for BPEL are, so I'm not sure what would be the best way to declare this in Tuscany. Perhaps some additional property elements in the componentType definition? In any case, it's not crucial for now. > > I'd appreciate any assistance you can give.... > Looking through your code, it looks pretty good. We'll need better error reporting on the compilation but I've seen you already have a todo tag here so nothing to add. We'll also probably need versioning soon, it's a pretty common in BPEL when you incrementally deploy new processes but for a first implementation, we can definitely live with it. Looks pretty nice overall, thanks a lot for your work! Matthieu > > Yours, Mike. > > > /* > * Licensed to the Apache Software Foundation (ASF) under one > * or more contributor license agreements. See the NOTICE file > * distributed with this work for additional information > * regarding copyright ownership. The ASF licenses this file > * to you under the Apache License, Version 2.0 (the > * "License"); you may not use this file except in compliance > * with the License. You may obtain a copy of the License at > * > * http://www.apache.org/licenses/LICENSE-2.0 > * > * Unless required by applicable law or agreed to in writing, > * software distributed under the License is distributed on an > * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY > * KIND, either express or implied. See the License for the > * specific language governing permissions and limitations > * under the License. > */ > package org.apache.tuscany.sca.implementation.bpel.ode; > > import java.io.File; > import java.io.InputStream; > import java.io.FileInputStream; > import java.io.IOException; > import java.net.URI; > import java.net.URL; > import java.util.Date; > import java.util.List; > import java.util.Collection; > import java.util.Map; > import java.util.HashMap; > import java.util.Arrays; > > import javax.wsdl.Definition; > import javax.wsdl.PortType; > import javax.xml.namespace.QName; > > import org.apache.ode.bpel.evt.BpelEvent.TYPE; > import org.apache.ode.bpel.iapi.Endpoint; > import org.apache.ode.bpel.iapi.ProcessConf; > import org.apache.ode.bpel.iapi.ProcessState; > import org.apache.ode.bpel.compiler.BpelC; > import org.w3c.dom.Node; > > import org.apache.tuscany.sca.implementation.bpel.BPELImplementation; > import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition; > import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterface; > import org.apache.tuscany.sca.assembly.Reference; > import org.apache.tuscany.sca.assembly.Service; > > public class TuscanyProcessConfImpl implements ProcessConf { > > private BPELImplementation implementation; > private Map<String, Endpoint> invokeEndpoints = null; > private Map<String, Endpoint> provideEndpoints = null; > private Map<QName, Node> properties = null; > private ProcessState processState; > > private final String TUSCANY_NAMESPACE = "http://tuscany.apache.org > "; > > /** > * Constructor for the ProcessConf implementation > * @param theImplementation the BPEL implementation for which this > is the ProcessConf > */ > public TuscanyProcessConfImpl( BPELImplementation theImplementation > ) { > this.implementation = theImplementation; > > processState = ProcessState.ACTIVE; > > // Compile the process > compile( getBPELFile() ); > } // end TuscanyProcessConfImpl constructor > > /** > * Returns the URI for the directory containing the BPEL process > */ > public URI getBaseURI() { > File theDir = getDirectory(); > return theDir.toURI(); > } > > /** > * Returns a String containing the (local) name of the file > containing the BPEL process > */ > public String getBpelDocument() { > URL processURL = > implementation.getProcessDefinition().getLocation(); > try { > return getRelativePath( getDirectory(), new File( > processURL.toURI() )); > } catch (Exception e) { > System.out.println( "Unable to resolve relative path > of BPEL process" + processURL ); > return null; > } // end try > } // end getBpelDocument > > /** > * Returns an InputStream containing the Compiled BPEL Process (CBP) > */ > public InputStream getCBPInputStream() { > // Find the CBP file - it has the same name as the BPEL > process and lives in the same > // directory as the process file > String cbpFileName = > implementation.getProcessDefinition().getName().getLocalPart() + ".cbp"; > File cbpFile = new File( getDirectory(), cbpFileName ); > if( cbpFile.exists() ) { > // Create an InputStream from the cbp file... > try { > return new FileInputStream( cbpFile ); > } catch ( Exception e ) { > System.out.println("Unable to open the cbp > file for BPEL process: " + > > implementation.getProcessDefinition().getName()); > } // end try > } else { > // Cannot find the cbp file > System.out.println("Cannot find the cbp file for > process: " + > > implementation.getProcessDefinition().getName()); > } // end if > // TODO - need better exception handling if we can't open > the cbp file for any reason > return null; > } // end getCBPInputStream > > /** > * Return the WSDL Definition for a given PortType > * @param portTypeName - the QName of the PortType > */ > public Definition getDefinitionForPortType( QName portTypeName ) { > // Find the named PortType in the list of WSDL interfaces > associated with this BPEL Process > Collection<WSDLInterface> theInterfaces = > implementation.getProcessDefinition().getInterfaces(); > for( WSDLInterface wsdlInterface : theInterfaces ) { > if ( wsdlInterface.getPortType().getQName().equals( > portTypeName ) ) { > // Extract and return the Definition > associated with the WSDLDefinition... > return > wsdlInterface.getWsdlDefinition().getDefinition(); > } // end if > } // end for > return null; > } > > /** > * Returns a WSDL Definition for a given Service QName > * > * 22/05/2008 - it is very unclear what this service QName is really > meant to be. > * From the handling of the deploy.xml file by the current ODE code, > it seems that the key link > * is from the Service QName to the PartnerLink name (done in the > deploy.xml file). > * > * The curious part about this is that the QName for the service is > ONLY defined in deploy.xml file > * and does not appear to relate to anything else, except for the > QName of the PartnerLink > * > * The PartnerLink name is the same as the name of the SCA service > (or reference) which in turn points > * at the PartnerLinkType which in turn points at an (WSDL) > interface definition. > */ > public Definition getDefinitionForService(QName serviceQName ) { > System.out.println("getDefinitionforService called for > service: " + serviceQName ); > // TODO Auto-generated method stub > return null; > } > > /** > * Returns the date of deployment of the process > * - for SCA returns the current time > */ > public Date getDeployDate() { > return new Date(); > } > > /** > * Returns userid of deployer > * - always "SCA Tuscany" for Tuscany... > */ > public String getDeployer() { > return "SCA Tuscany"; > } > > /** > * Returns a list of the files in the directory containing the BPEL > Process > */ > public List<File> getFiles() { > File theDir = getDirectory(); > List<File> theFiles = Arrays.asList( (File[]) > theDir.listFiles() ); > // TODO recurse into subdirectories > return theFiles; > } > > /** > * Returns a Map containing all the "invoke endpoints" - for which > read "SCA references" > * The map is keyed by partnerLink name and holds Endpoint objects > * > * TODO deal with service callbacks on bidirectional services > */ > public Map<String, Endpoint> getInvokeEndpoints() { > if( invokeEndpoints == null ) { > Map<String, Endpoint> invokeEndpoints = new > HashMap<String, Endpoint>(); > // Get a collection of the references > List<Reference> theReferences = > implementation.getReferences(); > // Create an endpoint for each reference, using the > reference name as the "service" > // name, combined with http://tuscany.apache.org to > make a QName > for( Reference reference : theReferences ) { > invokeEndpoints.put( reference.getName(), > new Endpoint( new QName( > TUSCANY_NAMESPACE, reference.getName() ), "ReferencePort")); > } // end for > } // end if > return invokeEndpoints; > } // end getInvokeEndpoints > > /** > * Returns the name of the directory containing the BPEL files > */ > public String getPackage() { > File theDir = getDirectory(); > return theDir.getName(); > } // end getPackage > > /** > * Return the BPEL Process ID - which is the same as the Process > QName > */ > public QName getProcessId() { > return getType(); > } // end getProcessID > > /** > * TODO - What are properties? > */ > public Map<QName, Node> getProperties() { > if ( properties == null ) { > properties = new HashMap<QName, Node>(); > } // end if > return properties; > } // end getProperties > > /** > * Returns a Map containing all the "provide endpoints" - for which > read "SCA services" > * The map is keyed by partnerLink name and holds Endpoint objects > * > * TODO deal with reference callbacks on bidirectional references > */ > public Map<String, Endpoint> getProvideEndpoints() { > if( provideEndpoints == null ) { > provideEndpoints = new HashMap<String, Endpoint>(); > // Get a collection of the references > List<Service> theServices = > implementation.getServices(); > // Create an endpoint for each reference, using the > reference name as the "service" > // name, combined with http://tuscany.apache.org to > make a QName > for( Service service : theServices ) { > provideEndpoints.put( service.getName(), > new Endpoint( new QName( > TUSCANY_NAMESPACE, service.getName() ), "ServicePort")); > } // end for > } // end if > return provideEndpoints; > } // end getProvideEndpoints > > /** > * Return the process state > */ > public ProcessState getState() { > return processState; > } > > /** > * Returns the QName of the BPEL process > */ > public QName getType() { > return implementation.getProcess(); > } > > /** > * Gets the process Version number > * - current code does not have versions for BPEL prcesses > */ > public long getVersion() { > return 0; > } > > /** > * Returns true if the supplied event type is enabled for any of the > scopes in the provided > * List > * @param scopeNames - list of BPEL process Scope names > * @param type - the event type > */ > public boolean isEventEnabled(List<String> scopeNames, TYPE type) { > // TODO - this will need an analysis of the content of the > BPEL process > // TODO Auto-generated method stub > return false; > } > > /** > * Returns whether the process is persisted in the store > * > * Returns true for SCA configuration as the BPEL process is in the > Domain config > */ > public boolean isTransient() { > return true; > } // end isTransient > > /** > * Compiles a BPEL process file into a compiled form CBP file in the > main directory > * (ie same directory as the BPEL process file) > * @param bpelFile - the BPEL process file > */ > private void compile( File bpelFile ) { > // Set up the compiler > BpelC compiler = BpelC.newBpelCompiler(); > // Provide a null set of initial properties for now > Map<QName, Node> processProps = new HashMap<QName, Node>(); > Map<String, Object> compileProps = new HashMap<String, > Object>(); > compileProps.put( BpelC.PROCESS_CUSTOM_PROPERTIES, processProps ); > compiler.setCompileProperties( compileProps ); > compiler.setBaseDirectory( getDirectory() ); > > // Run the compiler and generate the CBP file into the given > directory > try { > compiler.compile( bpelFile ); > } catch (IOException e) { > System.out.println("Compile error in " + bpelFile + e); > // TODO - need better exception handling here > } // end try > } // end compile > > /** > * Gets the directory containing the BPEL process > * @return > */ > private File getDirectory() { > File theDir = getBPELFile().getParentFile(); > return theDir; > } // end getDirectory > > /** > * Gets the File containing the BPEL process definition > * @return - the File object containing the BPEL process > */ > private File getBPELFile() { > File theProcess = new File( > implementation.getProcessDefinition().getURI() ); > return theProcess; > } // end getBPELFile > > /** > * Gets the relative path of a file against a directory in its > hierarchy > * @param base - the base directory > * @param path - the file > * @return > * @throws IOException > */ > private String getRelativePath(File base, File path) throws IOException > { > String basePath = base.getCanonicalPath(); > String filePath = path.getCanonicalPath(); > if (!filePath.startsWith(basePath)) throw new IOException("Invalid > relative path: base="+base+" path="+path); > String relative = filePath.substring(basePath.length()); > if (relative.startsWith(File.separator)) relative = > relative.substring(1); > return relative; > } // end getRelativePath > > } // end class TuscanyProcessConfImpl > > >