Skip to content

Commit

Permalink
Merge pull request #460 from david-gibbs-ig/fix-orchestra-with-update…
Browse files Browse the repository at this point in the history
…d-project-structure

Fix orchestra with updated project structure
  • Loading branch information
chrjohn authored Nov 30, 2023
2 parents e612ee6 + b9d0557 commit 8d23147
Show file tree
Hide file tree
Showing 257 changed files with 22,626 additions and 3,153 deletions.
13 changes: 7 additions & 6 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
env:
MAVEN_OPTS: "-Xms3g -Xmx6g -Djdk.xml.xpathExprGrpLimit=500 -Djdk.xml.xpathExprOpLimit=500"

strategy:
fail-fast: false
Expand All @@ -51,19 +53,18 @@ jobs:

# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
#- name: Autobuild
# env:
# uses: github/codeql-action/autobuild@v2

# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl

# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language

#- run: |
# make bootstrap
# make release
- run: |
mvn clean package -B -V -e -Pminimal-fix-latest -Dmaven.javadoc.skip=true -Dfindbugs.skip -Dcheckstyle.skip -Dpmd.skip=true -Dspotbugs.skip -Denforcer.skip -DskipTests -Dmaven.test.skip.exec -Dlicense.skip=true -Drat.skip=true -Dspotless.check.skip=true -D"java.util.logging.config.file"="logging.properties" -D"http.keepAlive"="false" -D"maven.wagon.http.pool"="false" -D"maven.wagon.httpconnectionManager.ttlSeconds"="120"
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
35 changes: 32 additions & 3 deletions .github/workflows/maven.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macOS-latest, windows-latest]
os: [ubuntu-latest, macOS-latest]
java: [8, 11, 17]
fail-fast: false
max-parallel: 4
Expand All @@ -26,7 +26,36 @@ jobs:
with:
distribution: 'temurin'
java-version: ${{ matrix.java }}
cache: 'maven'
- name: Test with Maven
env:
MAVEN_OPTS: "-Xms3g -Xmx3g"
run: mvn test -B -V -D"java.util.logging.config.file"="logging.properties" -D"http.keepAlive"="false" -D"maven.wagon.http.pool"="false" -D"maven.wagon.httpconnectionManager.ttlSeconds"="120"
MAVEN_OPTS: "-Xms3g -Xmx5g -Djdk.xml.xpathExprGrpLimit=500 -Djdk.xml.xpathExprOpLimit=500"
run: mvn install -B -V -Pminimal-fix-latest -D"java.util.logging.config.file"="logging.properties" -D"http.keepAlive"="false" -D"maven.wagon.http.pool"="false" -D"maven.wagon.httpconnectionManager.ttlSeconds"="120"

test-windows:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [windows-latest]
java: [8, 11, 17]
fail-fast: false
max-parallel: 3
name: Test JDK ${{ matrix.java }}, ${{ matrix.os }}

steps:
- uses: actions/checkout@v3
- name: Configure pagefile
uses: al-cheb/[email protected]
with:
minimum-size: 8GB
maximum-size: 16GB
- name: Set up Windows JDK
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: ${{ matrix.java }}
cache: 'maven'
- name: Test with Maven on Windows
env:
MAVEN_OPTS: "-Xms3g -Xmx5g -Djdk.xml.xpathExprGrpLimit=500 -Djdk.xml.xpathExprOpLimit=500"
run: mvn install -B -V -D"maven.javadoc.skip"="true" -P"skipBundlePlugin,minimal-fix-latest" -D"java.util.logging.config.file"="logging.properties" -D"http.keepAlive"="false" -D"maven.wagon.http.pool"="false" -D"maven.wagon.httpconnectionManager.ttlSeconds"="120"
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ target/
*.iws
# ignore NetBeans configuration
nb-configuration.xml
*.bak
.mvn/
mvn*
45 changes: 41 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,17 @@ Pull requests are always welcome! Best is if you added a unit test to show that

Fastest: clone the repo and issue the following command.
```
$ mvn clean package -Dmaven.javadoc.skip=true -DskipTests -PskipBundlePlugin
$ mvn clean package -Dmaven.javadoc.skip=true -DskipTests -PskipBundlePlugin,minimal-fix-latest -Djdk.xml.xpathExprGrpLimit=500 -Djdk.xml.xpathExprOpLimit=500
```

Slower: if you only want to skip the acceptance test suite:
```
$ mvn clean package -Dmaven.javadoc.skip=true -DskipAT=true -PskipBundlePlugin
$ mvn clean package -Dmaven.javadoc.skip=true -DskipAT=true -PskipBundlePlugin,minimal-fix-latest -Djdk.xml.xpathExprGrpLimit=500 -Djdk.xml.xpathExprOpLimit=500
```

Slow: if you want to run all tests:
```
$ mvn clean package -Dmaven.javadoc.skip=true -PskipBundlePlugin
$ mvn clean package -Dmaven.javadoc.skip=true -PskipBundlePlugin,minimal-fix-latest -Djdk.xml.xpathExprGrpLimit=500 -Djdk.xml.xpathExprOpLimit=500
```
NB: If you want to use the resulting JARs in an OSGi environment you'll have to omit the `-PskipBundlePlugin` option.

Expand All @@ -62,7 +62,7 @@ When the project is first created, it will not have the generated message classe

If the IDE reports some errors after the compilation with `mvn clean package`, try to use `mvn clean install`, like:
```
$ mvn clean install -Dmaven.javadoc.skip=true -DskipTests -PskipBundlePlugin
$ mvn clean install -Dmaven.javadoc.skip=true -DskipTests -PskipBundlePlugin,minimal-fix-latest -Djdk.xml.xpathExprGrpLimit=500 -Djdk.xml.xpathExprOpLimit=500
```

## configuration options
Expand Down Expand Up @@ -283,3 +283,40 @@ void sendOrderCancelRequest() throws SessionNotFound {
Session.sendToTarget(message, "TW", "TARGET");
}
```

## QuickFIX/J Runtime

This project builds artefacts for the standard published FIX specification versions from FIX 4.0 to FIX Latest.

* ```quickfixj-messages-fix40```
* ```quickfixj-messages-fix41```
* ```quickfixj-messages-fix42```
* ```quickfixj-messages-fix43```
* ```quickfixj-messages-fix44```
* ```quickfixj-messages-fix50```
* ```quickfixj-messages-fix50sp1```
* ```quickfixj-messages-fix50sp2```
* ```quickfixj-messages-fixlatest```
* ```quickfixj-messages-fixt11```
* ```quickfixj-messages-all``` - includes all of the above

These artefacts are <u>**test**</u> dependencies of ```quickfixj-core```. They are **not** specified as _runtime_ dependencies, this makes it easier to customise QuickFIX/J deployments.

If you have no need to customise a FIX integration then you can use the ```org.quickfixj``` artefacts built by this project. Simply include them as dependencies of your application.

Artefacts for unused FIX specification versions can be omitted from your runtime.
Many integrations will not require ```quickfixj-messages-all``` and need only depend on artefacts for a subset of the FIX standard versions. Please note that FIX Protocol versions 5.0 and later depend on ```quickfixj-messages-fixt11``` which provides the implementation for the FIXT1.1 transport messages.

Many integrations require specialisation of the FIX Messages, Components and/or Fields. This is accomplished by building and using custom artefacts. Please see [Customising QuickFIX/J](./customising-quickfixj.md) for more detail.

### Application Dependencies for QuickFIX/J Messages Build

![image info](./src/main/puml/dependencies_fixt11_fixlatest.png)

![image info](./src/main/puml/dependencies_qfj_all.png)

### Application Dependencies for Custom Messages Build

![image info](./src/main/puml/custom_dependencies.png)

![image info](./src/main/puml/custom_dependencies_fixt11_fixlatest.png)
94 changes: 94 additions & 0 deletions customising-quickfixj.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@

# Customising QuickFIX/J

The core QuickFIX/J module is agnostic to FIX Protocol Versions. At runtime a QuickFIX/J dictionary with supporting implementation packages is required to use type-safe classes.

The specification for a FIX integration is called a "Rules of Engagement". The Rules of Engagement can be customised with the mutual agreement of the respective counter-parties.

The message, component and field implementations can be provided by a specialised build, along with the corresponding QuickFIX/J dictionary for the custom Rules of Engagement.

The standard distribution of ```quickfixj-core``` can be used with custom artefacts. You need only build artefacts for versions of the Protocol that you use. These can be maintained independently from the QuickFIX/J project, while depending on the QuickFIX/J for the core functionality and tools.

To build custom artefacts it's helpful to understand how QuickFIX/J builds the Field, Component and Message classes from the QuickFIX/J dictionaries and from [FIX Orchestra](https://www.fixtrading.org/standards/fix-orchestra/).

The QuickFIX/J reference implementations for FIX versions FIX4.0 to FIX5.0sp2 and for FIXT1.1 are generated from the QuickFIX dictionaries for the specific version. The dictionaries are located in the ```src/main/resources``` directory of the respective modules of the ```quickfixj-messages``` module.
Maintaining the FIX4.0 to FIX5.0sp2 builds intentionally provides consistency with the prior QuickFIX/J 2 release in order to ease migration to QuickFIX/J 3.

The most recent standard is defined as [FIX Latest](https://www.fixtrading.org/online-specification/). The QuickFIX/J reference implementation for FIX Latest is generated from a [FIX Orchestra](https://www.fixtrading.org/standards/fix-orchestra/) repository file.
An implementation or customisation of the FIX Standars derived from the FIX Orchestra repository is known as an "_orchestration_".
The standard FIX Orchestra repository requires some modification to work well with QuickFIX/J.
This is done by the ```quickfixj-orchestration``` module.
The ```quickfixj-orchestration``` module publishes a modified Orchestra artefact which can then be the basis of a custom FIX Latest build using QuickFIX/J .

The complete reference FIX Latest specification results in a very large distribution.
To use FIX Latest, customisation of the [FIX Orchestra](https://www.fixtrading.org/standards/fix-orchestra/) repository is advisable.
Please see [QuickFIX/J Orchestration](./quickfixj-orchestration/readme.md) for details.

## Customisation Scenarios

### **Enable the use of ```BigDecimal``` for FIX Decimal Data Types**

This behaviour is controlled by the ```${generator.decimal}``` build property. It is "false" by default to avoid surprising side effects of incompatible data types.

To enable the use of ```BigDecimal``` in code generation, set the ```${generator.decimal}``` property to "true" in [quickfixj-messages](./quickfixj-messages/readme.md) and build the message artefacts.

```
<properties>
<generator.decimal>true</generator.decimal>
</properties>
```
See [QuickFIX/J Messages](./quickfixj-messages/readme.md) for details of the build and recommendation for **how to implement custom builds.**

### **Incompatible Data Types**

Some incompatible changes have occurred in the evolution of the FIX protocol. For example see below changes to the type of **OrderQty (38)** :

|FIX Version|Field Name|FIX Datatype|Base Type|QuickFIX/J Datatype|
|---|---|---|---|---|
|4.0|OrderQty|int|int|```int```|
|4.2|OrderQty|Qty|float|```Double``` or ```BigDecimal```|

Only one ```quickfix.Field``` class with the same name may be loaded by the Java classloader so only one version of this Field should be in the classpath. QuickFix/J also verifies the data type using the supplied QuickFIX "Dictionary".

Code generation using ```BigDecimal``` is incompatible at runtime with ```int``` for **OrderQty**. In this case, ```double``` is compatible with ```int``` at run time due to [widening primitive conversion](http://titanium.cs.berkeley.edu/doc/java-langspec-1.0/5.doc.html).

Runtime incompatibilities can be resolved by:
* Amending the QuickFIX Dictionary to coerce the code generation and/or validation
* Changing the ordering of code generation and/or overwrite behaviour of code generation
* Omitting incompatible versions from your customised build
* Building artefacts independently for the conflicting versions and ensuring they are not used them in the same runtime

See [QuickFIX/J Messages](./quickfixj-messages/readme.md) for details of the build and recommendation for **how to implement custom builds.**

### **Customising the FIX Protocol for specialised Rules of Engagement**

A Rules of Engagement can include customisation Messages, Components and Fields, including User Defined elements.

It is not necessary to maintain a fork of the entire QuickFIX/J project to provide customised QuickFIX Dictionaries and to
generate type-safe libraries that are interoperable with QuickFIX/J.

[FIX Orchestra](https://www.fixtrading.org/standards/fix-orchestra/) is intended for customisation to produce machine-readable Rules of Engagement.

Consider creating a new project (or projects) to build the Messages, Components and Fields as needed for your specific Rules of Engagement.

Edit the QuickFIX Dictionary or FIX Orchestra Repository (Orchestration) as required and
build the Messages, Components and Fields packages using the tools provided by the QuickFIX/J projects.

QuickFIX/J Dictionaries, FIX Orchestra Orchestrations and/or documents can also be generated.

See [QuickFIX/J Messages](./quickfixj-messages/readme.md) for details of the build and recommendation for **how to implement custom builds.**

### **Managing incompatibility with Prior Versions of QuickFIX/J**

From QuickFIX/J 3.0.0 the code generation for ```quickfix.Field``` prefers the FIX Orchestra Standard. This results in incompatible changes to the names of constants.

For example : ```SettlType.REGULAR_FX_SPOT_SETTLEMENT``` becomes ```SettlType.REGULAR```.

The required code changes may be trivial in most cases, but changes are elective.
The following describes how to use ```quickfixj-core``` from QuickFIX/J 3 without needing to implement code changes:
* build the required Message artefacts without the FIX Latest code generation. The Fields will then be generated only from legacy FIX Protocol Versions as they were prior to QuickFIX/J 3.0.0 - **or**
* if you want to use Messages, Components and/or Fields from FIX Latest while preferring legacy constants,
manipulate the order of code generation and/or the over-write behaviour of code behaviour to prefer earlier versions of FIX.
For example, generate FIX Latest first and overwrite the generated Field classes by subsequently running code generation for an earlier version.

See [QuickFIX/J Messages](./quickfixj-messages/readme.md) for details of the build and recommendation for **how to implement custom builds.**
Loading

0 comments on commit 8d23147

Please sign in to comment.