Skip to main content
Version: 2022.4

Server configuration - Genesis Router

Genesis Router is responsible for all communication between front end and back end. On the Genesis low-code platform, the front end connects to the back end through HTTPS or secure Websockets via a reverse proxy. This must run on the same instance as the back end.

The GENESIS_ROUTER service on the server acts as the endpoint for all API calls and listens (by default) to port 9064.

This is configured in the file genesis-router.kts.

Here is an example:

router {
webPort = 9064
socketPort = 9065

httpServerCodec {
maxInitialLineLength = 4096
maxHeaderSize = 8192
maxChunkSize = 8192
validateHeaders = true
initialBufferSize = 128
}
httpObjectAggregator {
maxContentLength = 262144
closeOnExpectationFailed = false
}

routes {
route(messageType = "ALL_ORDERS", process = "OEMS_DATASERVER")
route(messageType = "ALL_TRADES", process = "OEMS_DATASERVER")
route(messageType = "ALL_ORDER_AUDITS", process = "OEMS_DATASERVER")
}

allowList {
entry("ALL_ORDERS")
entry("ALL_TRADES")
entry("ALL_ORDER_AUDITS")
}
}

Router configuration

Let's have a look at the different options for configuring this file. You have seen some, but not all of these in the example above.

webPort This port is used for tcp/ip socket. You must declare a port, and it cannot be below 1024.

socketPort This port is used for http/websockets. You must declare a port, and it cannot be below 1024.

dataserverPollingTimeout This setting contains the timeout for polling the data-server resources in the system in seconds. Default value is 60 seconds.

authDisabled If set to true, this setting disables all authentication, and is used for development mode. Default value is false.

nettyLoggingEnabled This setting if set to true, enables internal netty logging. Default value false.

Netty configuration

httpServerCodecDefinition A combination of HttpRequestDecoder and HttpResponseEncoder, which enables easier server-side HTTP implementation. You can find more information in the netty documentation.

Different decoder options

  • maxInitialLineLength default value: 4096
  • maxHeaderSize default value: 8192
  • maxChunkSize default value: 8192
  • validateHeaders default value: true
  • initialBufferSize default value: 128

httpObjectAggregatorDefinition A ChannelHandler that aggregates an HttpMessage and its following HttpContents into a single FullHttpRequest or FullHttpResponse (depending on if it used to handle requests or responses) with no following HttpContents.

There is more information in the netty documentation.

  • maxContentLength The maximum length of the aggregated content in bytes. Default value: 262144
  • closeOnExpectationFailed If a 100-continue response is detected but the content length is too large, then true means close the connection. Otherwise, the connection will remain open and data will be consumed and discarded until the next request is received. Default value: false

Message routes

routes: You can redirect some microservice messages to particular processes by declaring new route blocks within this one.

route Is the defined route taking both a messageType and a specific process.

Blocked and allowed resources

You can control which resources are exposed to the front end by the Genesis Router using either allowList or blockList.

  • If you specify one or more resources as allowList, then only these resources (and the Genesis defaults) are accessible.
  • If you specify one or more resources as blockList, then these resources are not exposed. All other resources (including the Genesis defaults) are accessible.
  • If you don't specify any resources as either allowList or blockList, then all resources (including the Genesis defaults) are accessible.

The allowList and blockList tags are mutually exclusive. If you specify both, it will generate an error.

The default resources that are always exposed are:

  • EVENT_LOGIN_AUTH
  • EVENT_LOGOUT
  • MORE_ROWS
  • MORE_COLUMNS
  • DATA_LOGOFF
  • DATA_GET

Message type

entry Is the additional accepted messageType.

Configuring runtime

There are two important files in your application that contain configuration information; make sure that your Genesis Router is configured correctly in both of them:

  • application-name-processes.xml
  • application-name-service-definitions.xml

Configuring in processes.xml

Here is an example of the Genesis Router's configuration in an application's processes.xml file:

  <process name="GENESIS_ROUTER">
<start>true</start>
<scheduleRestart>true</scheduleRestart>
<groupId>GENESIS</groupId>
<options>-Xmx512m -DXSD_VALIDATE=false</options>
<module>router</module>
<package>global.genesis.router,global.genesis.console</package>
<config>router-process-config.kts</config>
<script>genesis-router.kts</script>
<language>pal</language>
<classpath>genesis-console-*.jar</classpath>
<description>Socket, Websocket and HTTP proxy which routes incoming messages to GENESIS microservices</description>
</process>

For more information on the tags that can be set within the configuration for your application, go to our page on processes.xml.

Configuring in service-definitions.xml

Here is an example of the Genesis Router's configuration in an application's processes.xml file:

  <service host="localhost" name="GENESIS_ROUTER" port="9017"/>

For more information on the attributes that can be set in this file, go to our page on service definitions.

Custom endpoints

To create a custom endpoint using the Genesis Router, simply implement the WebEndpoint interface provided by Genesis Router. Call upon the registerEndpoint method of an injected WebEndpointRegistry object.

In the following examples, a FileEndpointCommon class has also been created to hold utility methods that may be needed across multiple endpoints:

FileEndpointCommon

public class FileEndpointCommon {
companion object {
const val ENDPOINT_NAME = "file-handler"
}
}

FileProcessor

@Module
class FileProcessorKotlin @Inject constructor(
private val registry: WebEndpointRegistry
) : WebEndpoint {
@PostConstruct
fun init() {
registry.registerEndpoint(FileEndpointCommon.ENDPOINT_NAME, this)
}

override fun allowedMethods(): Set<RequestType> {
return ALLOWED_HTTP_METHODS
}

override fun name(): String {
return "upload"
}

override fun process(s: String, fullHttpRequest: FullHttpRequest, channel: Channel): Any {
LOG.debug("Hit {}/{} endpoint", FileEndpointCommon.ENDPOINT_NAME, name())
//This is where you would make calls to other services and libraries with the newly uploaded file.
val responseJson = "{ \"Result\": \"Successful upload\"}".toByteArray(StandardCharsets.UTF_8)
val responseBuffer = Unpooled.wrappedBuffer(responseJson)
val response = DefaultFullHttpResponse(
HttpVersion.HTTP_1_1,
HttpResponseStatus.OK,
responseBuffer
)
response.headers().add(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_JSON)
HttpUtil.setContentLength(response, responseJson.size.toLong())
return response
}

override fun requiresAuth(): Boolean {
return if (System.getProperty("TEST_MODE") != null) {
false
} else {
super.requiresAuth()
}
}

companion object {
private val LOG = LoggerFactory.getLogger(FileProcessorKotlin::class.java)
private val ALLOWED_HTTP_METHODS: Set<RequestType> = ImmutableSet.of(RequestType.POST)
}
}

Testing the Genesis Router

To create unit tests for Genesis Router, you can extend the AbstractGenesisTestSupport class and specify the genesis-router.kts as the Script file name. Examples of how you would initialise a test extending this class are provided below.

More information about how testing works is in our section on Integration testing.

class TestEndpoint : AbstractGenesisTestSupport<GenesisSet>(
GenesisTestConfig {
packageNames = mutableListOf("global.genesis.router", "org.file.processor")
genesisHome = "/genesisHome"
scriptFileName = "genesis-router.kts"
parser = { it }
}
) {
override fun createDictionary(): GenesisDictionary = testDictionary()}

@Test
fun testRouterEndPoint() {
val client = HttpClient.newHttpClient()
val request = HttpRequest
.newBuilder(URI("http://localhost:9064/file-handler/upload"))
.version(HttpClient.Version.HTTP_1_1)
.POST(HttpRequest.BodyPublishers.ofString("TEXT"))
.build()
val response = client.send(request, HttpResponse.BodyHandlers.ofString())
Assert.assertEquals("{ \"Result\": \"Successful upload\"}", response.body())
}