Refactor to clean up packages in the t-model and to introduce a simpler to implement t-engine base. The new t-engines (tika, imagemagick, libreoffice, pdfrenderer, misc, aio, aspose) and t-router may be used in combination with older components as the API between the content Repo and between components has not changed. As far as possible the same artifacts are created (the -boot projects no longer exist). They may be used with older ACS repo versions. The main changes to look for are: * The introduction of TransformEngine and CustomTransformer interfaces to be implemented. * The removal in t-engines and t-router of the Controller, Application, test template page, Controller tests and application config, as this is all now done by the t-engine base package. * The t-router now extends the t-engine base, which also reduced the amount of duplicate code. * The t-engine base provides the test page, which includes drop downs of known transform options. The t-router is able to use pipeline and failover transformers. This was not possible to do previously as the router had no test UI. * Resources including licenses are automatically included in the all-in-one t-engine, from the individual t-engines. They just need to be added as dependencies in the pom. * The ugly code in the all-in-one t-engine and misc t-engine to pick transformers has gone, as they are now just selected by the transformRegistry. * The way t-engines respond to http or message queue transform requests has been combined (eliminates the similar but different code that existed before). * The t-engine base now uses InputStream and OutputStream rather than Files by default. As a result it will be simpler to avoid writing content to a temporary location. * A number of the Tika and Misc CustomTransforms no longer use Files. * The original t-engine base still exists so customers can continue to create custom t-engines the way they have done previously. the project has just been moved into a folder called deprecated. * The folder structure has changed. The long "alfresco-transform-..." names have given way to shorter easier to read and type names. * The t-engine project structure now has a single project rather than two. * The previous config values still exist, but there are now a new set for config values for in files with names that don't misleadingly imply they only contain pipeline of routing information. * The concept of 'routing' has much less emphasis in class names as the code just uses the transformRegistry. * TransformerConfig may now be read as json or yaml. The restrictions about what could be specified in yaml has gone. * T-engines and t-router may use transform config from files. Previously it was just the t-router. * The POC code to do with graphs of possible routes has been removed. * All master branch changes have been merged in. * The concept of a single transform request which results in multiple responses (e.g. images from a video) has been added to the core processing of requests in the t-engine base. * Many SonarCloud linter fixes.
5.7 KiB
Transform specific code
To create a new t-engine an author uses a base t-engine (a Spring Boot
application) and implements the following interfaces. An implementation of
the CustomTransformer
provides the actual transformation code and the
implementation of the TransformEngine
says what it is capable of
transforming. The TransformConfig
is normally read from a json file on the
classpath. Multiple CustomTransformer
implementations may be in a singe
t-engine. As a result the author can concentrate on the code that transforms
one format to another without really worrying about all the plumbing.
Typically, the transform specific code uses a 3rd party library or an
external executable which needs to be added to the Docker image.
package org.alfresco.transform;
import org.alfresco.transform.config.TransformConfig;
import org.alfresco.transformer.probes.ProbeTestTransform;
import java.util.Set;
/**
* Interface to be implemented by transform specific code. Provides information
* about the t-engine as a whole. So that it is automatically picked up, it must
* exist in a package under {@code org.alfresco.transform} and have the Spring
* {@code @Component} annotation.
*/
public interface TransformEngine
{
/**
* @return the name of the t-engine. The t-router reads config from t-engines
* in name order.
*/
String getTransformEngineName();
/**
* @return a definition of what the t-engine supports. Normally read from a json
* Resource on the classpath.
*/
TransformConfig getTransformConfig();
/**
* @return a ProbeTestTransform (will do a quick transform) for k8 liveness and
* readiness probes.
*/
ProbeTransform getProbeTransform();
}
implementations of the following interface provide the actual transform code.
package org.alfresco.transform;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;
/**
* Interface to be implemented by transform specific code. The
* {@code transformerName} should match the transformerName in the
* {@link TransformConfig} returned by the {@link TransformEngine}. So that it is
* automatically picked up, it must exist in a package under
* {@code org.alfresco.transform} and have the Spring {@code @Component} annotation.
*
* Implementations may also use the {@link TransformManager} if they wish to
* interact with the base t-engine.
*/
public interface CustomTransformer
{
String getTransformerName();
void transform(String sourceMimetype, InputStream inputStream,
String targetMimetype, OutputStream outputStream,
Map<String, String> transformOptions,
TransformManager transformManager) throws Exception;
}
The implementation of the following interface is provided by the t-base,
allows the CustomTransformer
to interact with the base t-engine. The
creation of Files is discouraged as it is better not to leave files on disk.
package org.alfresco.transform.base;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;
/**
* Allows {@link CustomTransformer} implementations to interact with the base
* t-engine.
*/
public interface TransformManager
{
/**
* Allows a CustomTransformer to use a local source File rather than the
* supplied InputStream. To avoid creating extra files, if a File has already
* been created by the base t-engine, it is returned.
*/
File createSourceFile();
/**
* Allows a CustomTransformer to use a local target File rather than the
* supplied OutputStream. To avoid creating extra files, if a File has already
* been created by the base t-engine, it is returned.
*/
File createTargetFile();
/**
* Allows a single transform request to have multiple transform responses. For
* example, images from a video at different time offsets or different pages of
* a document. Following a call to this method a transform response is made with
* the data sent to the current {@code OutputStream}. If this method has been
* called, there will not be another response when {@link CustomTransformer#
* transform(String, InputStream, String, OutputStream, Map, TransformManager)}
* returns and any data written to the final {@code OutputStream} will be
* ignored.
* @param index returned with the response, so that the fragment may be
* distinguished from other responses. Renditions use the index
* as an offset into elements. A {@code null} value indicates
* that there is no more output and any data sent to the current
* {@code outputStream} will be ignored.
* @param finished indicates this is the final fragment. {@code False} indicates
* that it is expected there will be more fragments. There need
* not be a call with this parameter set to {@code true}.
* @return a new {@code OutputStream} for the next fragment. A {@code null} will
* be returned if {@code index} was {@code null} or {@code
* finished} was {@code true}.
* @throws TransformException if a synchronous (http) request has been made as
* this only works with requests on queues, or the first call to
* this method indicated there was no output, or another call is
* made after it has been indicated that there should be no more
* fragments.
* @throws IOException if there was a problem sending the response.
OutputStream respondWithFragment(Integer index);
}