{"id":22220605,"url":"https://github.com/fix8mt/ufeed_bindings_java","last_synced_at":"2025-03-25T07:41:38.106Z","repository":{"id":215362115,"uuid":"425228686","full_name":"fix8mt/ufeed_bindings_java","owner":"fix8mt","description":"Java language binding for UFEed.","archived":false,"fork":false,"pushed_at":"2021-11-16T06:36:46.000Z","size":2028,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-01-30T07:12:43.063Z","etag":null,"topics":["fix","fix-engine","fix8","fix8-market","fix8pro","fixengine","fixprotocol","google-protocol-buffers","high-performance","java","low-latency","middleware","zeromq"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-2.1","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fix8mt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2021-11-06T11:39:17.000Z","updated_at":"2023-11-16T12:58:44.000Z","dependencies_parsed_at":"2024-01-04T02:16:11.657Z","dependency_job_id":"07d7b982-5958-43ec-802e-6363175f7e91","html_url":"https://github.com/fix8mt/ufeed_bindings_java","commit_stats":null,"previous_names":["fix8mt/ufeed_bindings_java"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fix8mt%2Fufeed_bindings_java","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fix8mt%2Fufeed_bindings_java/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fix8mt%2Fufeed_bindings_java/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fix8mt%2Fufeed_bindings_java/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fix8mt","download_url":"https://codeload.github.com/fix8mt/ufeed_bindings_java/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245422922,"owners_count":20612725,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fix","fix-engine","fix8","fix8-market","fix8pro","fixengine","fixprotocol","google-protocol-buffers","high-performance","java","low-latency","middleware","zeromq"],"created_at":"2024-12-02T23:09:18.403Z","updated_at":"2025-03-25T07:41:38.069Z","avatar_url":"https://github.com/fix8mt.png","language":"Java","readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.fix8mt.com\"\u003e\u003cimg src=\"fix8mt_Master_Logo_Green_Trans.png\" width=\"200\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n# UFEed Java Bindings\n-   [Introduction](#introduction)\n-   [Getting started](#getting-started)\n-   [Interface](#interface)\n    -   [UFEMessage and UFEMessage Builder](#ufemessage-and-ufemessage-builder)\n    -   [UFEedClient](#ufeedclient)\n-   [Constants](#constants)\n    -   [FIX variants constants](#fix-variants-constants)\n-   [Building](#building)\n\n------------------------------------------------------------------------\n\n# Introduction\n\nThe UFEed Java Adapter (`UFEed_Java`) provides a low level java interface to the\nUFEGW. Interactions with the UFEGW are based around a `UFEedClient`\nobject from `com.fix8mt.ufe.ufeedclient` namespace which can be used to\nsend and receive Messages to and from the UFEGW.\n\nUse the following [Universal FIX engine documentaion](https://fix8mt.atlassian.net/wiki/spaces/FMT/pages/634438/Universal+FIX+Engine+Home) for a reference.\n\nFeatures of `UFEedClient`:\n\n-   System API support (see 4. Implementation Guide - Section 1.3)\n\n-   Business API support (eg. NewOrderSingle and standard FIX messages)\n\n-   Provides a 4-way communications API in order to make requests,\n    publish messages, receive responses and subscribe to broadcast\n    messages\n\n-   User defined implementation of callback interface to handle these\n    PUB, SUB, REQ and REP message events\n\n-   Dynamic configuration of PUB, SUB, REQ, REP addressing and topics\n\n-   Internal session management\n\nFeatures of a `UFEMessage/UFEMessage.Builder`:\n\n-   A generic container of fields, i.e. tag/typed value pairs with\n    possible nested messages called groups\n\n-   Smart field creation and access, rendering field value to ival, sval\n    or fval depending on context\n\n-   Named Message setters/getters (name, long_name, seq, service_id,\n    subservice_id)\n\n# Getting started\n\nThe `UFEed_Java` is provided as a Java project with jar\npackages for external dependencies: ZeroMQ, Google Protobuf, getopt.\nWithin the target build directory of `UFEed_Java` we find the following directory\nstructure (example is Linux):\n\n```\nufeed_bindings_java\n├── packages\n│   ├── java-getopt-1.0.14.jar\n│   ├── jzmq-core-3.1.1-SNAPSHOT.jar\n│   ├── jzmq-devices-3.1.1-SNAPSHOT.jar\n│   ├── jzmq-jni-3.1.1-SNAPSHOT.jar\n│   ├── jzmq-jni-3.1.1-SNAPSHOT-native-amd64-Linux.jar\n│   ├── protobuf-java-3.7.1.jar\n│   ├── protobuf-java-util-3.7.1.jar\n│   └── ufeedclient-19.6.0.jar\n└── samples\n    └── com\n        └── fix8mt\n            └── ufe\n                └── sample\n                    └── Sample.java\n```\n\n# Interface\n\nThe main `UFEed_Java` interfaces/classes are `UFEMessage`, `UFEMEssage.Builder`\nand `UFEedClient`. Most of `UFEMessage` field setters and `UFEedClient`\nsetters follow 'builder' pattern to simplify Java language constructs\n(i.e. setters return the reference to an object it was called from):\n\n```java\nUFEMessage.Builder login = _uc.createMessage()\n    .setLongName(\"login\")\n    .setType(st_system)\n    .setServiceId(UFE_CMD_LOGIN)\n    .addField(UFE_CMD, UFE_CMD_LOGIN, fl_system)\n    .addField(UFE_LOGIN_ID, \"webuser\", fl_system)\n    .addField(UFE_LOGIN_PW, \"5e884898da28047151d0e56f8dc\", fl_system);\n```\n\n## UFEMessage and UFEMessage Builder\n\nThe UFEMessage class provides some wrapping logic around the internal\nGoogle Protobuf `WireMessage` format utilized by the UFEGW. Messages are\nobjects with which requests are made from the `UFEed_Java` to the UFEGW.\n\n`UFEedClient::createMessage()` factory method shall be used to create a\nmessage. `UFEMessage` is a final, i.e immutable just after\n`UFEMessage::build()` is called to finalize `UFEMessage`.\n`UFEMessage.Builder` class is for creating the message until it is\nfinalized.\n\n`UFEMessage.Builder` class:\n\n```java\npublic static class Builder {\n    /**\n    * ctors\n    * @param wm WireMessage to copy from or null\n    */\n    public Builder(WireMessage wm);\n    public Builder(WireMessage.Builder wmb);\n\n    /**\n    * Returns WireMessage builder\n    * @return WireMessage builder\n    */\n    public WireMessage.Builder getWireMessageBuilder();\n\n    /**\n    * Longname\n    * @return message long name\n    */\n    public String getLongName();\n    public Builder setLongName(String longName);\n\n    /**\n    * Type\n    * @return message type\n    */\n    public WireMessage.Type getType();\n    public Builder setType(WireMessage.Type type);\n\n    /**\n    * Service id\n    * @return message service id\n    */\n    int getServiceId();\n    public Builder setServiceId(int serviceId);\n\n    /**\n    * Adds typed field to message\n    * @param tag field tag\n    * @param val field value\n    * @param loc field location\n    * @return self\n    */\n    public Builder addField(int tag, long val, UFEFieldLocation loc);\n    public Builder addField(int tag, ByteString val, UFEFieldLocation loc);\n    public Builder addField(int tag, String val, UFEFieldLocation loc);\n    public Builder addField(int tag, char val, UFEFieldLocation loc);\n    public Builder addField(int tag, double val, UFEFieldLocation loc);\n    public Builder addField(int tag, boolean val, UFEFieldLocation loc);\n    public Builder addField(int tag, Instant val, UFEFieldLocation loc);\n    public Builder addField(int tag, UUID val, UFEFieldLocation loc);\n    public Builder addField(int tag, Message.Status val, UFEFieldLocation loc);\n    public Builder addField(int tag, Object val, UFEFieldLocation loc) throws UFEedException;\n    public Builder addFields(Iterable\u003cUFEField\u003e fields);\n    public Builder addGroup(int tag, GroupBuilderRef group, GroupTransformFunc tr, UFEFieldLocation loc);\n    public Builder addGroupItem(UFEField.Builder group);\n\n    /**\n    * Builds UFEMessage when composing is complete. Message is ummutable agter the call.\n    * @return Immutable composed UFEMessage\n    */\n    public UFEMessage build();\n}\n```\n\n`UFEMessage` class:\n\n```java\npublic class UFEMessage {\n    /**\n    * Creates a message builder. When it's done, call builder.build() that returns UFEMessage.\n    * @param wm WireMessage to copy from or null\n    * @return message builder\n    */\n    public static Builder newBuilder(WireMessage wm);\n\n    /**\n    * Returns inner WireMessage\n    * @return inner WireMessage\n    */\n    public WireMessage getWireMessage();\n\n    /**\n     * Returns mapped fields hash map\n     * @return mapped fields hash map\n     */\n    public HashMap\u003cInteger, UFEField\u003e getFields();\n\n    /**\n     * Returns mapped groups hash map\n     * @return mapped groups hash map\n     */\n    public HashMap\u003cInteger, List\u003cUFEMessage\u003e\u003e getGroups();\n\n    /**\n     * Finds field by given tag\n     * @param tag tag to find field\n     * @return found field or null\n     */\n    public UFEField findField(int tag);\n\n    /**\n     * Finds field value by given tag\n     * @param tag tag to find field\n     * @return found field or null\n     */\n    public Object findFieldValue(int tag);\n\n    /**\n    * Finds group by given tag\n    * @param tag tag to find group\n    * @return found group of null\n    */\n    public List\u003cUFEMessage\u003e findGroup(int tag) {\n        return _groups.get(tag);\n    }\n}\n```\n\n`UFEMessage` and `UFEMessage.Builder` usage sample:\n\n```java\n// logon\nUFEMessage.Builder login = _uc.createMessage()\n    .setLongName(\"login\")\n    .setType(st_system)\n    .setServiceId(UFE_CMD_LOGIN)\n    .addField(UFE_CMD, UFE_CMD_LOGIN, fl_system)\n    .addField(UFE_LOGIN_ID, \"webuser\", fl_system)\n    .addField(UFE_LOGIN_PW, \"5e884898da28047151d0e56f8dc\", fl_system);\n// UFEedClient send methods accept builder class\nUFEMessage loginMsg = login.build();\nUFEField loginId = loginMsg.findField(UFE_LOGIN_ID);\nObject loginPw = loginMsg.findFieldValue(UFE_LOGIN_PW);\n```\n\n`UFEMessage` and `UFEMessage.Builder` create a `NewOrderSingle` message\nwith groups:\n\n```java\nUFEMessage.Builder.GroupBuilderRef grp = new UFEMessage.Builder.GroupBuilderRef();\nUFEMessage.Builder nos = _uc.createMessage()\n    .setLongName(\"NewOrderSingle\")\n    .setType(st_fixmsg)\n    .setServiceId(1)\n    .setName(MsgType.NEWORDERSINGLE)\n    .addField(ClOrdID.tag, \"123\", fl_body)\n    .addField(TransactTime.tag, Instant.now(), fl_body)\n    .addField(ExecInst.tag, ExecInst.ALL_OR_NONE, fl_body)\n    .addField(OrdType.tag, OrdType.LIMIT, fl_body)\n    .addField(Side.tag, Side.BUY, fl_body)\n    .addGroup(NoAllocs.tag, grp, (builder, group) -\u003e {\n        builder.addGroupItem(group)\n            .setLongName(\"NoAlloc\")\n            .setType(st_fixmsg)\n            .setSeq(1)\n            .addField(AllocAccount.tag, \"ABC\", fl_body)\n            .addField(AllocQty.tag, 2, fl_body);\n        builder.addGroupItem(group)\n            .setLongName(\"NoAlloc\")\n            .setType(st_fixmsg)\n            .setSeq(2)\n            .addField(AllocAccount.tag, \"CDE\", fl_body)\n            .addField(AllocQty.tag, 4, fl_body);\n    }, fl_body);\n```\n\n## UFEedClient\n\nThe `UFEedClient` class is used as the interface to make both System and\nBusiness API calls to the UFEGW. Sessions between `UFEedClient` and the\nUFEGW are made up of ZeroMQ PUB/SUB and REQ/REP sockets. The network\naddresses and message topics inherent to these sockets are configurable\nvia `UFEedClient`. In addition, the `UFEedClient` manages these UFEGW\nsessions on behalf of the user (after the user has successfully logged\nin).\n\n`UFEedClient` provides a callback interface called `Listener` that must\nbe implemented by `UFEedClient` consumer:\n\n```java\npublic interface Listener {\n    /**\n    * Called when subscription message received\n    * @param message received subscription message\n    */\n    void subscriptionMessageReceived(UFEMessage message);\n\n    /**\n    * Called when responder message received\n    * @param message received responder message\n    */\n    void responderMessageReceived(UFEMessage message);\n\n    /**\n    * Called when response message received\n    * @param message received response message\n    */\n    void responseMessageReceived(UFEMessage message);\n\n    /**\n    * Called when authentication is requested\n    * @param user user to check\n    * @param password user password to check\n    * @return true for successful authentication, otherwise false\n    */\n    boolean authenticateRequested(String user, String password);\n\n    /**\n    * Called when ZeroMQ error happened\n    * @param error ZMQ error code\n    * @return true to continue, false to stop processing loop\n    */\n    boolean zeroMQErrorHappened(int error);\n\n    /**\n    * Called when error happened\n    * @param error error message\n    * @param exception exception happened\n    * @return true to continue, false to stop processing loop\n    */\n    boolean errorHappened(String error, Exception exception);\n}\n```\n:::\n:::\n\n`UFEedClient` is configured with `UFEConfiguration` class:\n\n```java\npublic class UFEedConfiguration {\n    /**\n    * Subscriber endpoint, defaults to \"tcp://127.0.0.1:55745\"\n    * @return subscriber endpoint\n    */\n    public String getSubscriber();\n    public UFEedConfiguration setSubscriber(String subscriber);\n\n    /**\n    * Requester endpoint, defaults to \"tcp://127.0.0.1:55746\"\n    * @return requester endpoint\n    */\n    public String getRequester();\n    public UFEedConfiguration setRequester(String requester);\n\n    /**\n    * Publisher endpoint, defaults to \"tcp://*:55747\"\n    * @return publisher endpoint\n    */\n    public String getPublisher();\n    public UFEedConfiguration setPublisher(String publisher);\n\n    /**\n    * Responder endpoint, defaults to \"tcp://*:55748\"\n    * @return responder endpoint\n    */\n    public String getResponder();\n    public UFEedConfiguration setResponder(String responder);\n\n    /**\n    * Subscriber topic, defaults to \"ufegw-publisher\"\n    * @return subscriber topic\n    */\n    public String getSubscriberTopic();\n    public UFEedConfiguration setSubscriberTopic(String subscriberTopic);\n\n    /**\n    * Requester topic, defaults to \"ufegw-responder\"\n    * @return requester topic\n    */\n    public String getRequesterTopic();\n    public UFEedConfiguration setRequesterTopic(String requesterTopic);\n\n    /**\n    * Publisher topic, defaults to \"ufeedclient-publisher\"\n    * @return publisher topic\n    */\n    public String getPublisherTopic();\n    public UFEedConfiguration setPublisherTopic(String publisherTopic);\n\n    /**\n    * Responder topic, defaults to \"ufeedclient-responder\"\n    * @return responder topic\n    */\n    public String getResponderTopic();\n    public UFEedConfiguration setResponderTopic(String responderTopic);\n\n    /**\n    * ZMQ max IO threads\n    * @return ZMQ max io threads\n    */\n    public int getMaxIoThreads();\n    public UFEedConfiguration setMaxIoThreads(int maxIoThreads);\n\n    /**\n    * Poll interval in milliseconds\n    * @return poll interval in milliseconds\n    */\n    public int getPollIntervalMs();\n    public UFEedConfiguration setPollIntervalMs(int pollIntervalMs);\n}\n```\n\n`UFEedClient` interface:\n\n```java\npublic class UFEedClient implements AutoCloseable {\n    /**\n    * Constructs UFEedClient\n    * @param configuration configuration to use\n    */\n    public UFEedClient(UFEedConfiguration configuration, Listener listener);\n\n    /**\n    * Implementation for AutoClosable::close() - frees ZMQ resources\n    * @throws Exception\n    */\n    @Override\n    public void close() throws Exception;\n\n    /**\n    * UFEedClient configuration\n    * @return UFEedClient configuration\n    */\n    public UFEedConfiguration getConfiguration();\n\n    /**\n    * Starts UFEedClient. When started in synchronous mode (wait = true)\n    * it does not return until stop() is called from a different thread.\n    * @param wait true for synchronous call, false for asynchronous\n    */\n    public void start(boolean wait);\n\n    /**\n    * Stops UFEedClient\n    * @throws InterruptedException\n    */\n    public void stop() throws InterruptedException;\n\n    /**\n    * Creates UFEMessage\n    * @param longName message long name\n    * @param type message type\n    * @param serviceId message service id\n    * @return message builder\n    */\n    public UFEMessage.Builder createMessage(String longName, WireMessage.Type type, int serviceId);\n    public UFEMessage.Builder createMessage(WireMessage wm);\n\n    /**\n    * Synchronously sends request to UFE and waits for UFE response\n    * @param request request to send\n    * @return received response\n    * @throws UFEedException thrown if no session token found\n    * @throws InvalidProtocolBufferException thrown if protobuf parsing failed\n    */\n    public UFEMessage request(UFEMessage.Builder request) throws UFEedException, InvalidProtocolBufferException;\n\n    /**\n    * Send message to responder channel\n    * IMPORTANT: Must be called from responderMessageReceived callback thread as much as possible\n    * @param msg message to send\n    */\n    public void respond(UFEMessage msg);\n\n    /**\n    * UFEedClient callback interface\n    */\n    public interface Listener { ... }\n}\n```\n\n`UFEedClient` usage sample:\n\n```java\nUFEedClient _uc = new UFEedClient(new UFEedConfiguration().setSubscriber(SUBSCRIBER_DEFAULT).setResponderTopic(\"ufegw-requester\"),\n  new UFEedClient.Listener() {\n    @Override\n    public void subscriptionMessageReceived(UFEMessage message) { ... }\n    @Override\n    public void responderMessageReceived(UFEMessage message) { ... }\n    @Override\n    public void responseMessageReceived(UFEMessage message) { ... }\n    @Override\n    public boolean authenticateRequested(String user, String password) { ... }\n    @Override\n    public boolean zeroMQErrorHappened(int error) { ... }\n    @Override\n    public boolean errorHappened(String error, Exception exception) { ... }\n});\n_uc.start(false);\n\n// logon\nUFEMessage.Builder login = _uc.createMessage(\"login\", st_system, UFE_CMD_LOGIN)\n    .addField(UFE_CMD, UFE_CMD_LOGIN, fl_system)\n    .addField(UFE_LOGIN_ID, \"webuser\", fl_system)\n    .addField(UFE_LOGIN_PW, \"5e884898da28047151d0e56f8dc\", fl_system);\ntry {\n    UFEMessage response = _uc.request(login);\n    if (response.findField(UFE_SESSION_TOKEN) == null)\n        throw new UFEedException(\"Session token is missing\");\n    Object sessToken = response.findFieldValue(UFE_SESSION_TOKEN);\n    if (sessToken == null)\n        throw new UFEedException(\"Session token is missing #1\");\n    if(!(sessToken instanceof UUID))\n        throw new UFEedException(\"Session token is of unexpected type\");\n    if (sessToken.toString().isEmpty())\n        throw new UFEedException(\"Session token is empty\");\n\n    // service list request\n    response = _uc.request(_uc\n        .createMessage(\"service_list\", st_system, UFE_CMD_SERVICE_LIST)\n        .addField(UFE_CMD, UFE_CMD_SERVICE_LIST, fl_system));\n...\n} finally {\n    _uc.stop();\n    _uc.close();\n}\n```\n\n# Constants\n\nThe `UFEed_Java` maintains a list of constant values that translate to integer\ncodes in the UFEGW. These integer codes are used to identify System API\nservices as well as general FIX functionality. A full list of these\nconstants is available at `src/com/fix8mt/ufe/ufeedclient/Consts.java`.\nThe file with constants could be regenrated using `genconsts` project.\n\n## FIX variants constants\n\nThe `UFEed_Java` provides constants for all stock FIX variants:\n\n```java\nimport com.fix8mt.ufe.FIX50SP2.ufe_java_fields_fix50sp2.*;\n...\nUFEMessage.Builder nos = _uc.createMessage()\n    .setLongName(\"NewOrderSingle\")\n    .setType(st_fixmsg)\n    .setServiceId(1)\n    .setName(MsgType.NEWORDERSINGLE)\n    .addField(ClOrdID.tag, \"123\", fl_body)\n    .addField(TransactTime.tag, Instant.now(), fl_body)\n    .addField(ExecInst.tag, ExecInst.ALL_OR_NONE, fl_body)\n    .addField(OrdType.tag, OrdType.LIMIT, fl_body)\n    .addField(Side.tag, Side.BUY, fl_body);\n```\n\n# Building\n\nThe `UFEed_Java` build follows a standard Java build pattern. Jetbrains IntelliJ project files are provided.\n\nThe `UFEed_Java` provides a sample to use as a starting point for UFEed Java\ndevelopment. The sample is under root folder. To build/run sample, you\nhave to set Java path to `UFEedClient` jar and all the dependency jars\nand call `Sample.Main()`:\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffix8mt%2Fufeed_bindings_java","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffix8mt%2Fufeed_bindings_java","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffix8mt%2Fufeed_bindings_java/lists"}