### MithraTestResource usage example in test setup and teardown Source: https://goldmansachs.github.io/reladomo/mithraTestResource/ReladomoTestResource.html Example of using MithraTestResource in a test case. In the setup method, an instance is created, databases are created and populated, and setUp() is called; in the teardown method, tearDown() cleans the data. Refer to MithraTestAbstract.java for a complete example. ```java MihtraTestResource mihtraTestResource = null; **protected** **void** setUp() **throws** Exception { String xmlFile = **"MithraConfigurationTest.xml"** mithraTestResource = **new** MithraTestResource(xmlFile); ConnectionManagerForTests connMgrForTestDb = ConnectionManagerForTests.getInstance(**"test_db"**); ConnectionManagerForTests connMgrForDeskDb = ConnectionManagerForTests.getInstance(**"desk_db"**); mithraTestResource.createSingleDatabase( connMgForTestDb, **"mithraTestData.txt"**); mithraTestResource.createDatabaseForStringSourceAttribute( connMgForDeskDb, **"deskA"**, **"mithraTestDataForDesk.txt"**); mithraTestResource.createDatabaseForStringSourceAttribute( connMgForDeskDb, **"deskB"**, **"mithraTestDataForDesk.txt"**); mithraTestResource.setUp(); } **protected** **void** tearDown() **throws** Exception { mithraTestResource.tearDown(); } ``` -------------------------------- ### setUp method signature Source: https://goldmansachs.github.io/reladomo/mithraTestResource/ReladomoTestResource.html Performs several setup actions: gets the Mithra manager, sets the transaction manager provider, populates database tables from the file specified during database creation, and loads the Reladomo cache. This method needs to be called from the setUp() method in the test cases. ```java **public** **void** setUp() **throws** Exception ``` -------------------------------- ### Typical setUp Method with MithraTestResource Source: https://goldmansachs.github.io/reladomo/mithraTestResource/ReladomoTestResource.html Shows a typical setUp method: creates a MithraTestResource with a runtime configuration, obtains a ConnectionManagerForTests for 'test_db', calls createDatabaseForStringSourceAttribute to load test data, and calls setUp. tearDown should call mithraTestResource.tearDown(). ```java **this**.mithraTestResource = **new** MithraTestResource (**"services/Reladomo/TestPostingEngineReladomoConfiguration.xml"**); ConnectionManagerForTests connectionManagerForTestDb = ConnectionManagerForTests.getInstance(**"test_db"**); **this**.mithraTestResource.createDatabaseForStringSourceAttribute( connectionManager,TEST_ACMAP_CODE, **"testIntradayData.txt"**); **this**.mithraTestResource.setUp(); ``` -------------------------------- ### SQL logging output from Reladomo test run Source: https://goldmansachs.github.io/reladomo-kata/reladomo-tour-docs/tour-guide.html Example output from running a test with SQL logging enabled. It shows SQL statements executed for in-memory database setup, test data insertion, and finder queries, including the number of objects retrieved and timing information. Logs are generated for both main code and test code like MithraTestResource when it populates the in-memory H2 database. ```text // in-memory database setup H2DbServer - Starting H2 database Server H2DbServer - H2 database Server Started Customer - executing statement drop table CUSTOMER Customer - executing statement create table CUSTOMER ( CUSTOMER_ID integer not null,FIRST_NAME varchar(64) not null,LAST_NAME varchar(64) not null,COUNTRY varchar(48) not null ) Customer - executing statement CREATE UNIQUE INDEX I_CUSTOMER_PK ON CUSTOMER (CUSTOMER_ID) CustomerAccount - executing statement drop table CUSTOMER_ACCOUNT CustomerAccount - executing statement create table CUSTOMER_ACCOUNT ( ACCOUNT_ID integer not null,CUSTOMER_ID integer not null,ACCOUNT_NAME varchar(48) not null,ACCOUNT_TYPE varchar(16) not null,BALANCE double ) CustomerAccount - executing statement CREATE UNIQUE INDEX I_CUSTOMER_ACCOUNT_PK ON CUSTOMER_ACCOUNT (ACCOUNT_ID) Customer - executing statement truncate table CUSTOMER CustomerAccount - executing statement truncate table CUSTOMER_ACCOUNT // inserting test data into the in-memory database Customer - executing statement INSERT INTO CUSTOMER (CUSTOMER_ID,FIRST_NAME,LAST_NAME,COUNTRY) values (1,'mickey','mouse','USA') Customer - executing statement INSERT INTO CUSTOMER (CUSTOMER_ID,FIRST_NAME,LAST_NAME,COUNTRY) values (2,'minnie','mouse','USA') Customer - executing statement INSERT INTO CUSTOMER (CUSTOMER_ID,FIRST_NAME,LAST_NAME,COUNTRY) values (3,'peter','pan','Neverland') CustomerAccount - executing statement INSERT INTO CUSTOMER_ACCOUNT (ACCOUNT_ID,CUSTOMER_ID,ACCOUNT_NAME,ACCOUNT_TYPE,BALANCE) values (100,1,'mickey mouse club','savings',5000.0) CustomerAccount - executing statement INSERT INTO CUSTOMER_ACCOUNT (ACCOUNT_ID,CUSTOMER_ID,ACCOUNT_NAME,ACCOUNT_TYPE,BALANCE) values (101,2,'retirement','savings',10000.0) CustomerAccount - executing statement INSERT INTO CUSTOMER_ACCOUNT (ACCOUNT_ID,CUSTOMER_ID,ACCOUNT_NAME,ACCOUNT_TYPE,BALANCE) values (102,3,'fun stuff','checking',3000.0) // SQL executed to satisfy a finder query Customer - connection:1690573857 find with: select t0.CUSTOMER_ID,t0.FIRST_NAME,t0.LAST_NAME,t0.COUNTRY from CUSTOMER t0 where t0.CUSTOMER_ID = 1 Customer - retrieved 1 objects, 13.0 ms per CustomerAccount - connection:1690573857 find with: select t0.ACCOUNT_ID,t0.CUSTOMER_ID,t0.ACCOUNT_NAME,t0.ACCOUNT_TYPE,t0.BALANCE from CUSTOMER_ACCOUNT t0 where t0.CUSTOMER_ID = 1 CustomerAccount - retrieved 1 objects, 1.0 ms per ``` -------------------------------- ### SimpleBankTestData.txt example Source: https://goldmansachs.github.io/reladomo-kata/reladomo-tour-docs/tour-guide.html Example test data file used to test the REST API built in chapter 4. It defines two classes, Customer and CustomerAccount, with sample rows for each. ```text class simplebank.domain.Customer customerId, firstName, lastName, country 1, "mickey", "mouse", "USA" 2, "minnie", "mouse", "USA" 3, "peter", "pan", "Neverland" class simplebank.domain.CustomerAccount accountId, customerId, accountName, accountType, balance 100, 1, "mickey mouse club", "savings", 5000 101, 2, "retirement", "savings", 10000 102, 3, "fun stuff", "checking", 3000 ``` -------------------------------- ### Command line to launch Reladomo NotificationServer Source: https://goldmansachs.github.io/reladomo/notification/Notification.html Starts a Reladomo Notification server with java -classpath and -Dport. For dual notification, run this twice, preferably on two different physical machines. ```bash java -classpath -Dport= com.gs.fw.common.mithra.notification.server.NotificationServer ``` -------------------------------- ### Implement GET API with findByPrimaryKey and findMany Source: https://goldmansachs.github.io/reladomo-kata/reladomo-tour-docs/tour-guide.html Implements GET API methods for Customer. findByPrimaryKey fetches a single object by its primary key, while findMany with an eq operation fetches all customers with a given last name. ```java **public** Customer getCustomerById(**int** customerId) { **return** CustomerFinder.findByPrimaryKey(customerId); } **public** CustomerList getCustomersByLastName(String lastName) { **return** CustomerFinder.findMany(CustomerFinder.lastName().eq(lastName)); } ``` -------------------------------- ### Start TCP Notification Server Source: https://goldmansachs.github.io/reladomo/presentations/mithraAdvancedUseCases/ReladomoAdvancedUseCases.xhtml Starts the TCP notification server. The port is specified via the -Dport system property. This server is easiest to set up and works well for a small number of servers and clients (less than 1000). ```bash java –classpath –Dport= com.gs.fw.common.mithra .notification.server.NotificationServer ``` -------------------------------- ### Create and customize SerializationConfig Source: https://goldmansachs.github.io/reladomo/serialization/Serialization.html Start with a shallow configuration using SerializationConfig.shallowWithDefaultAttributes, then customize it with withDeepFetches and withAnnotatedMethods. The configuration is immutable, so each call returns a new instance. ```java SerializationConfig config = SerializtionConfig.shallowWithDefaultAttributes( OrderFinder.getFinderInstance()); ``` ```java config = config.withDeepFetches(OrderFinder.orderStatus(), OrderFinder.items()); config = config.withAnnotatedMethods(SerialView.Shorter.class); ``` -------------------------------- ### SimulatedSequence strategy MithraObject example Source: https://goldmansachs.github.io/reladomo/primaryKeyGenerator/PrimaryKeyGenerator.html Complete MithraObject XML example using the SimulatedSequence strategy for the transactionId primary key. The SimulatedSequence element specifies sequenceName="AccountTransactionSequence" and sequenceObjectFactoryName="com.gs.fw.common.mithra.test.domain.MithraTestSequenceObjectFactory". ```xml **** ****com.gs.fw.common.mithra.test.domain**** ****AccountTransaction**** ****ACCOUNT_TRANSACTION**** **** **** **** **** ... **** ``` -------------------------------- ### Get objects between two dates with equalsEdgePoint Source: https://goldmansachs.github.io/reladomo/mithrafaq/ReladomoFaq.html Example of using equalsEdgePoint to get all objects between two dates. The resulting FooList contains all foos in the range; adjust equality signs or dates for open or closed ranges. ```java Operation op = FooFinder.businessDate().equalsEdgePoint(); **if** (endDate != infinity) { op = op.and(FooFinder.businessDateFrom().lessThanEquals(endDate); } op = op.and(FooFinder.businessDateTo().greaterThanEquals(startDate)); FooList foos = **new** FooList(op); ``` -------------------------------- ### Reladomo test data file format and example Source: https://goldmansachs.github.io/reladomo/mithraTestResource/ReladomoTestResource.html The first block shows the generic format for a Reladomo test data file: a class name line, an attribute name line, and then rows of comma-separated values. The second block is a concrete example for the ExchangeRate class, using the attributes currency, source, date, and exchangeRate. Values are comma-separated; strings and dates are quoted, and null is written without quotes. ```text class , ... , ... , ... ... ... , ... ``` ```text **class** com.gs.fw.common.mithra.test.domain.ExchangeRate currency, source, date, exchangeRate **"EUR"**, 10, **"2004-09-30 18:30:00.0"**, 1.25 **"USD"**, 10, **"2004-09-30 18:30:00.0"**, 1 **"GBP"**, 10, **"2004-09-30 18:30:00.0"**, 1.81 **"JPY"**, 10, **"2004-09-30 18:30:00.0"**, .009 ``` -------------------------------- ### SimpleBankServer main class with Reladomo init and Grizzly server Source: https://goldmansachs.github.io/reladomo-kata/reladomo-tour-docs/tour-guide.html Main server class that initializes Reladomo with the MithraRuntime XML and starts a Grizzly HTTP server with the Jersey resource. It sets a transaction timeout of 60 seconds and loads the runtime configuration from the classpath. ```java public class SimpleBankServer { private ResourceConfig config; public SimpleBankServer(String runtimeConfigXML) throws Exception { this.initReladomo(runtimeConfigXML); } protected void initReladomo(String runtimeConfigXML) throws Exception { MithraManager mithraManager = MithraManagerProvider.getMithraManager(); mithraManager.setTransactionTimeout(60 * 1000); InputStream stream = loadReladomoXMLFromClasspath(runtimeConfigXML); MithraManagerProvider.getMithraManager().readConfiguration(stream); stream.close(); } private InputStream loadReladomoXMLFromClasspath(String fileName) throws Exception { InputStream stream = SimpleBankServer.class .getClassLoader().getResourceAsStream(fileName); if (stream == null) { throw new Exception("Failed to locate " + fileName + " in classpath"); } return stream; } protected void initResources() { this.config = new ResourceConfig(CustomerResource.class); config.register(JacksonFeature.class); config.register(SimpleBankJacksonObjectMapperProvider.class); } public void start() throws IOException { initResources(); URI baseUri = UriBuilder.fromUri("http://localhost/").port(9998).build(); HttpServer server = GrizzlyHttpServerFactory.createHttpServer(baseUri, config); server.start(); } public static void main(String[] args) throws Exception { String runtimeConfigXML = "reladomoxml/SimpleBankRuntimeConfiguration.xml"; new SimpleBankServer(runtimeConfigXML).start(); } // elided for brevity } ``` -------------------------------- ### SimpleBankTestRuntimeConfiguration.xml Source: https://goldmansachs.github.io/reladomo-kata/reladomo-tour-docs/tour-guide.html This is the complete SimpleBankTestRuntimeConfiguration.xml file. It configures a single ConnectionManagerForTests with a testResource property and two domain classes. Use this file as the test runtime configuration for the simple-bank example. ```XML **** **** **** **** **** **** **** ``` -------------------------------- ### forEachWithCursor - normal loop Source: https://goldmansachs.github.io/reladomo/presentations/mithraAdvancedUseCases/ReladomoAdvancedUseCases.xhtml Normal way to iterate over a list of products. This loads all results into memory on the first call to size() or get(). ```java ProductList list = ProductFinder.findMany(op); **for**(**int** i = 0; i < list.size(); i++) { Product prod = list.get(i); ... } ``` -------------------------------- ### In-line SQL Example: Appending SQL conditions and executing update Source: https://goldmansachs.github.io/reladomo/presentations/mithraFeatures/ReladomoFeatures.xhtml Builds a SQL statement by appending conditions and timestamp parameters, then executes it as an update. Uses the basic date provider for as-of and eternity dates, and catches DataStoreException to log errors. ```java sb.append(**" and NPV.THRU_Z >= ? "**); **this**.addTimestampParameter(**this**.getBasicDateProvider().getAsOfDate()); sb.append(**" and NPV.IN_Z < ? "**); **this**.addTimestampParameter(**this**.getBasicDateProvider().getEternity()); sb.append(**" and NPV.OUT_Z >= ? "**); **this**.addTimestampParameter(**this**.getBasicDateProvider().getEternity()); sb.append( **"and F.CURRENCY = 'USD' "**); sb.append(**" and BTV.TRAN_SETTLE_D = F.VALUE_DATE"**); sb.append(**" and F.FROM_Z < ? "**); **this**.addTimestampParameter(**this**.getBasicDateProvider().getAsOfDate()); sb.append(**" and F.THRU_Z >= ? "**); **this**.addTimestampParameter(**this**.getBasicDateProvider().getAsOfDate()); sb.append(**" and F.IN_Z < ? "**); **this**.addTimestampParameter(**this**.getBasicDateProvider().getEternity()); sb.append(**" and F.OUT_Z >= ? "**); **this**.addTimestampParameter(**this**.getBasicDateProvider().getEternity()); sb.append(**" and BTV.PROD_SEC_ID_I = C.PROD_SEC_ID_I"**); **this**.getStatementWrapper().setStatementString(sb.toString()); **this**.executeUpdateStatement(); } **catch** (DataStoreException e) { **this**.getLogger().error(e); } } ``` -------------------------------- ### BitemporalChainingInAction run method Source: https://goldmansachs.github.io/reladomo-kata/reladomo-tour-docs/tour-guide.html Main test method that orchestrates the bitemporal chaining example by calling helper methods for account creation, fetching, balance updates, and dumping customer data. ```java @Test public void run() throws Exception { int accountId = 12345; createAccount("2017-01-01", accountId); fetchAccountWithBusinessDate("2017-01-01", accountId); updateBalance("2017-01-20", accountId, 200); dumpCustomerAccount(accountId); updateBalance("2017-01-17", "2017-01-25", accountId, 50); dumpCustomerAccount(accountId); balanceAsOfJan12_OnJan23(accountId); dumpCustomer(1); } ``` -------------------------------- ### Initialize Reladomo with MithraManager Source: https://goldmansachs.github.io/reladomo-kata/reladomo-tour-docs/tour-guide.html Initializes Reladomo by reading the runtime configuration from the classpath. Sets a 60-second transaction timeout and closes the configuration stream after reading. The start() method is left empty for application logic. ```java **public** **class** SimpleBankApp { **public** **static** **void** main(String[] args) **throws** Exception { **new** SimpleBankApp().start(); } **public** SimpleBankApp() **throws** Exception { **this**.initReladomo(); } **private** **void** initReladomo() **throws** Exception { MithraManager mithraManager = MithraManagerProvider.getMithraManager(); mithraManager.setTransactionTimeout(60 * 1000); InputStream stream = loadReladomoXMLFromClasspath(**"SimpleBankRuntimeConfiguration.xml"**); MithraManagerProvider.getMithraManager().readConfiguration(stream); stream.close(); } **private** **void** start() { _//implement app logic_ } _// elided for brevity_ } ``` -------------------------------- ### SimpleBankAPITest.java with MithraTestResource Source: https://goldmansachs.github.io/reladomo-kata/reladomo-tour-docs/tour-guide.html Complete test class showing how to use MithraTestResource to load the MithraClassList and initialize the test database with test data. It sets up the test environment and verifies a GET request to /api/customer/1 returns the expected customer and account details. ```java **public** **class** SimpleBankAPITest { **private** String testRuntimeConfigXML = **"testconfig/SimpleBankTestRuntimeConfiguration.xml"**; _@Before_ **public** **void** setup() **throws** Exception { intializeReladomoForTest(); initializeApp(); } **private** **void** intializeReladomoForTest() { MithraTestResource testResource = **new** MithraTestResource(testRuntimeConfigXML); ConnectionManagerForTests connectionManager = ConnectionManagerForTests.getInstance(**"test_db"**); testResource.createSingleDatabase(connectionManager, **"testconfig/SimpleBankTestData.txt"**); testResource.setUp(); } **private** **void** initializeApp() **throws** Exception { **new** SimpleBankServer(testRuntimeConfigXML).start(); } _@Test_ **public** **void** testGetCustomer() { WebTarget target = webTarget(**"/api/customer/1"**); Response response = target.request(MediaType.APPLICATION_JSON_TYPE).get(); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); Customer mickey = response.readEntity(Customer.**class**); assertEquals(1, mickey.getCustomerId()); assertEquals(**"mickey"**, mickey.getFirstName()); assertEquals(**"mouse"**, mickey.getLastName()); CustomerAccountList mickeysAccounts = mickey.getAccounts(); assertEquals(1, mickeysAccounts.size()); CustomerAccount clubhouseAccount = mickeysAccounts.get(0); assertEquals(100, clubhouseAccount.getAccountId()); assertEquals(**"mickey mouse club"**, clubhouseAccount.getAccountName()); assertEquals(**"savings"**, clubhouseAccount.getAccountType()); assertEquals(5000, clubhouseAccount.getBalance(), 0); } _// elided for brevity_ } ``` -------------------------------- ### Generated SQL for fetching latest account (OUT_Z = Infinity) Source: https://goldmansachs.github.io/reladomo-kata/reladomo-tour-docs/tour-guide.html SQL generated by Reladomo for the fetchLatestAccount example. It selects the latest state of the account by filtering on OUT_Z = Infinity (9999-12-01 23:59:00.000). ```sql **select** t0.ACCOUNT_ID,t0.CUSTOMER_ID,t0.ACCOUNT_NAME,t0.ACCOUNT_TYPE,t0.BALANCE,t0.IN_Z,t0.OUT_Z **from** CUSTOMER_ACCOUNT t0 **where** t0.ACCOUNT_ID = 12345 **and** t0.OUT_Z = **'9999-12-01 23:59:00.000'** ``` -------------------------------- ### MithraObject element with XSD reference Source: https://goldmansachs.github.io/reladomo/mithrafaq/ReladomoFaq.html Example of a MithraObject element with a reference to the mithraobject.xsd schema. Adding this reference enables IDE code assist for Reladomo XML configuration. ```xml **** ``` -------------------------------- ### Insert MithraList with SimulatedSequence using insertAll() Source: https://goldmansachs.github.io/reladomo/primaryKeyGenerator/PrimaryKeyGenerator.html Example of inserting a MithraList using the SimulatedSequence strategy. The convenience method is not called; instead, insertAll() ensures the primary key generator has a batch with enough capacity and each MithraObject checks, generates, and sets its primary key if necessary. ```java ... AccountTransactionList list1 = **new** AccountTransactionList(); AccountTransaction accountTransaction1 = null; **for** (**int** i = 0; i < 25; i++) { accountTransaction1 = **new** AccountTransaction(); accountTransaction1.setTransactionDate(**new** Timestamp(System.currentTimeMillis())); accountTransaction1.setTransactionDescription(**"Transaction failure: "**+i); accountTransaction1.setDeskId(**"A"**); list1.add(accountTransaction1); } list1.insertAll(); ... ``` -------------------------------- ### Create new order with items and product descriptions Source: https://goldmansachs.github.io/reladomo/userguide/ReladomoTutorial.html Example 1: Creates a new Order with 3 OrderItems and 3 ProductDescriptions inside executeTransaction. Uses cascadeInsert() on the Order to insert all related objects automatically; alternatively, call insert() on each new object individually. ```java public class CreateNewOrder implements TransactionalCommand { public void addOrderItem(OrderItemDetails item;) { myOrderDetailsList.add(item); // Keep a list of } public void setOrderDescription(String orderDescription) { this.orderDescription = orderDescription; } public Object executeTransaction() throws Throwable { Order = new Order(); order.setDescription(this.orderDescription) for (OrderItemDetails details : myOrderDetailsList) { OrderItem orderItem = new OrderItem(); // Set values on orderItem from details object .... ProductInfo productInfo = new ProductInfo(); // Set values on productInfo from details object ...... // Associate ProductInfo Object with OrderItem orderItem.setProductInfo(productInfo); // Associate OrderItem to Order order.getOrderItems().add(OrderItem) } //Insert all the objects order.cascadeInsert(); } } ``` -------------------------------- ### Test deep-fetch with database retrieve count Source: https://goldmansachs.github.io/reladomo/mithrafaq/ReladomoFaq.html Verifies that deep-fetching works by checking that the number of database retrieves does not increase after exercising the fetched list. The example fetches employees with demographics and addresses, then asserts the retrieve count remains unchanged. ```java _// deep-fetch a list_ EmployeeList employees = EmployeeFinder.findMany(EmployeeFinder.all()); employees.deepFetch(EmployeeFinder.demographics()); employees.deepFetch(EmployeeFinder.personalInfo().addresses()); _// ensure the resulting list is resolved, e.g. by calling forceResolve()_ _// verify we got the expected number of employees_ assertEquals(15, employees.size()); _// Now grab a count of DB retrieves so far:_ **int** count = MithraManagerProvider.getMithraManager().getDatabaseRetrieveCount(); _// do something interesting that exercises the list you fetched, e.g._ **int** totalAddressCount = 0; _// (there's better ways of getting this, but this is just a made-up example)_ **for** (Employee employee : employees) { totalAddressCount += employee.getAddresses().size(); } _// if your deep-fetches were good, then there should not have been any additional retrieves made, so:_ assertEquals(count, MithraManagerProvider.getMithraManager().getDatabaseRetrieveCount()); ``` -------------------------------- ### MithraTestSequenceObjectFactory implementation Source: https://goldmansachs.github.io/reladomo/primaryKeyGenerator/PrimaryKeyGenerator.html Example factory class implementing MithraSequenceObjectFactory. It looks up an existing MithraTestSequence by name, creates and inserts a new one with the initial value if not found, and returns it. ```java **public** **class** MithraTestSequenceObjectFactory **implements** MithraSequenceObjectFactory { **public** MithraSequence getMithraSequenceObject(String sequenceName, Object sourceAttribute, **int** initialValue) { Operation op = MithraTestSequenceFinder.simulatedSequenceName().eq(sequenceName); MithraTestSequence mithraTestSequence = MithraTestSequenceFinder.findOne(op); **if** (mithraTestSequence == null) { mithraTestSequence = **new** MithraTestSequence() mithraTestSequence.setSequenceName(sequenceName); mithraTestSequence.setNextId(initialValue); mithraTestSequence.insert(); } **return** mithraTestSequence; } } ``` -------------------------------- ### CustomerResource Jersey REST resource with create and get Source: https://goldmansachs.github.io/reladomo-kata/reladomo-tour-docs/tour-guide.html Jersey resource class for Customer REST API. It provides create (POST) and get (GET) endpoints using Reladomo CRUD operations. The class is annotated with @Path("/api/customer") and uses @FormParam for input. ```java @Path("/api/customer") public class CustomerResource { @POST public Response createCustomer( @FormParam("customerId") int customerId, @FormParam("firstName") String firstName, @FormParam("lastName") String lastName) { Customer customer = new Customer(); customer.setCustomerId(customerId); customer.setFirstName(firstName); customer.setLastName(lastName); customer.insert(); return Response.ok().build(); } @GET @Path("/{id}") @Produces(MediaType.APPLICATION_JSON) public Serialized getCustomerById(@PathParam("id") int customerId) throws JsonProcessingException { Customer customer = CustomerFinder.findByPrimaryKey(customerId); return new Serialized<>(customer, serializationConfig); } // elided for brevity } ``` -------------------------------- ### MithraTestApp.java: Reladomo initialization and startup Source: https://goldmansachs.github.io/reladomo/userguide/ReladomoTutorial.html Java class that initializes Reladomo by loading MithraRuntimeConfig XML files and setting the transaction timeout. The main method loads two configuration files and the loadMithraConfigurationXml method reads the XML from the classpath, throwing an exception if the file is missing. ```java **public** **class** MithraTestApp { **private** Logger logger = LoggerFactory.createLogger(MithraTestApp.**class**.getName()); **private** **static** **int** maxTransactionTimeout = 120; **public** Logger getLogger() { **return** logger; } **public** **void** setLogger(Logger logger) { **this**.logger = logger; } **public** **static** **int** getMaxTransactionTimeout() { **return** maxTransactionTimeout; } **public** **static** **void** setMaxTransactionTimeout(**int** maxTransactionTimeout) { MithraTestApp.maxTransactionTimeout = maxTransactionTimeout; } **public** **static** **void** main(String[] args) { MithraTestApp app = **new** MithraTestApp(); **try** { app.initialiseMithra(); app.loadMithraConfigurationXml(**"MithraRuntimeConfig1.xml"**); _// optionally load multiple config files:_ app.loadMithraConfigurationXml(**"MithraRuntimeConfig2.xml"**); _//Do your thing!!_ } **catch**(Exception e) { System.out.println(e); } } **private** **void** loadMithraConfigurationXml(String mithraXml) **throws** Exception { logger.info(**"Mithra configuration XML is "** + mithraXml); InputStream is = MithraTestApp.**class**.getClassLoader().getResourceAsStream(mithraXml); **if** (is == null) **throw** **new** Exception(**"can't find file: "** + mithraXml + **" in classpath"**); MithraManagerProvider.getMithraManager().readConfiguration(is); **try** { is.close(); } **catch** (java.io.IOException e) { logger.error(**"Unable to initialise Reladomo!"**, e); **throw** **new** Exception(**"Unable to initialise Reladomo!"**, e); } logger.info(**"Reladomo configuration XML "** + mithraXml+**" is now loaded."**); } **private** **void** initialiseMithra() **throws** Exception { **try** { logger.info(**"Transaction Timeout is "** + **this**.getMaxTransactionTimeout()); MithraManager mithraManager = MithraManagerProvider.getMithraManager(); mithraManager.setTransactionTimeout(**this**.getMaxTransactionTimeout()); } **catch** (Exception e) { logger.error(**"Unable to initialise Reladomo!"**, e); **throw** **new** Exception(**"Unable to initialise Reladomo!"**, e); } logger.info(**"Reladomo has been initialised!"**); } } ``` -------------------------------- ### Set up Reladomo TCP Notification Server and client Source: https://goldmansachs.github.io/reladomo/mithrafaq/ReladomoFaq.html Sets up the Reladomo TCP Notification Server and configures client processes to use it. The server command must be run with the required jars and a port; the client code must point to the same host and port. ```java java -classpath **<** all_the_required_jars** >** -Dport=**<** some_port_number** >** com.gs.fw.common.mithra.notification.server.NotificationServer ``` ```java MithraManagerProvider.getMithraManager().setNotificationEventManager( new MithraNotificationEventManagerImpl(new TcpMessagingAdapterFactory(host, port))); ``` -------------------------------- ### Max strategy MithraObject example Source: https://goldmansachs.github.io/reladomo/primaryKeyGenerator/PrimaryKeyGenerator.html Complete MithraObject XML example using the Max strategy for the transactionId primary key. The attribute is declared with javaType long and primaryKeyGeneratorStrategy="Max". ```xml **** ****com.gs.fw.common.mithra.test.domain**** ****AccountTransactionMax**** ****ACCOUNT_TRANSACTION_MAX**** **** **** ... **** ``` -------------------------------- ### createAccount method with bitemporal constructor Source: https://goldmansachs.github.io/reladomo-kata/reladomo-tour-docs/tour-guide.html Creates a customer and account with a specified business date. Uses a transactional command and explicitly sets the processing date via doNotDoThisInProduction, which should not be done in production. ```java **private** **void** createAccount(String date, **int** accountId) { Timestamp jan1 = DateUtils.parse(date); MithraManagerProvider.getMithraManager().executeTransactionalCommand(tx -> { _// Simulate the db change happening on a specific date - Do not do this in production_ doNotDoThisInProduction(date, tx); Customer customer = **new** Customer(jan1); customer.setFirstName(**"mickey"**); customer.setLastName(**"mouse"**); customer.setCustomerId(1); customer.setCountry(**"usa"**); CustomerAccount account = **new** CustomerAccount(jan1); account.setAccountId(accountId); account.setBalance(100); account.setAccountType(**"savings"**); account.setAccountName(**"retirement"**); customer.getAccounts().add(account); customer.cascadeInsert(); **return** null; }); } ``` -------------------------------- ### Reladomo object query example Source: https://goldmansachs.github.io/reladomo/architecture/ReladomoInternalArchitecture.html Example of a Reladomo query using the generated OrderFinder to filter orders by customer name 'Fred' and having unshipped items. The query uses the eq operation and the 'and' boolean operation. ```java OrderList result = **new** OrderList( OrderFinder.customerName().eq(**"Fred"**).and( OrderFinder.items().shipped().eq(false))); ``` -------------------------------- ### Configure XAConnectionManager and implement getConnection() Source: https://goldmansachs.github.io/reladomo/mithrafaq/ReladomoFaq.html Configure an XAConnectionManager for Reladomo and expose it through a SourcelessConnection manager. The first block sets up the pool with Sybase-specific properties; the second implements getConnection() by delegating to the manager. Use this instead of a random connection manager. ```java connectionManager = **new** XAConnectionManager(); connectionManager.setLdapName(ldapName); connectionManager.setJdbcUser(user); connectionManager.setJdbcPassword(password); connectionManager.setDefaultSchemaName(schemaName); connectionManager.setPoolName(ldapName + **" connection pool"**); connectionManager.setInitialSize(1); connectionManager.setPoolSize(100); connectionManager.setUseStatementPooling(true); connectionManager.setProperty(**"com.gs.fw.aig.jdbc.global.DataSourceImpl"**, **"com.sybase.jdbc4.jdbc.SybDataSource"**); connectionManager.setProperty(**"com.gs.fw.aig.jdbc.global.ConnectionPoolDataSourceImpl"**, **"com.sybase.jdbc4.jdbc.SybConnectionPoolDataSource"**); connectionManager.setProperty(**"com.sybase.jdbc4.jdbc.SybDataSource.REPEAT_READ"**, **"false"**); connectionManager.initialisePool(); ``` ```java **public** Connection getConnection() { **return** **this**.connectionManager.getConnection(); } ``` -------------------------------- ### Get Reladomo connection manager via FooFinder.getMithraObjectPortal().getDatabaseObject().getConnectionManager() Source: https://goldmansachs.github.io/reladomo/mithrafaq/ReladomoFaq.html Use this to get a reference to the connection manager used by Reladomo for a given finder. This avoids mentioning the connection manager class name twice. Note that this code is not 3-tier safe. ```java FooFinder.getMithraObjectPortal().getDatabaseObject().getConnectionManager() ``` -------------------------------- ### Enable Reladomo SQL logging in Logback (logback.xml) Source: https://goldmansachs.github.io/reladomo-kata/reladomo-tour-docs/tour-guide.html Logback configuration that enables SQL logging for Reladomo by setting the loggers com.gs.fw.common.mithra.sqllogs, com.gs.fw.common.mithra.batch.sqllogs, and com.gs.fw.common.mithra.test.sqllogs to DEBUG. The root logger remains at INFO and output goes to the console. SQL logging can be very verbose and should generally not be enabled by default in production. ```xml **** **** **** ****%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n**** **** **** ******** ******** ******** __ **** **** **** **** ``` -------------------------------- ### Composite Primary Key Source: https://goldmansachs.github.io/reladomo-kata/reladomo-tour-docs/tour-guide.html Example of defining a primary key composed of multiple attributes by setting primaryKey to true on each. ```xml **** **** ``` -------------------------------- ### Single Attribute Primary Key Source: https://goldmansachs.github.io/reladomo-kata/reladomo-tour-docs/tour-guide.html Example of defining a single attribute as the primary key within an Attribute tag. ```xml **** ``` -------------------------------- ### Runtime Configuration with Multiple Databases Source: https://goldmansachs.github.io/reladomo/mithraTestResource/ReladomoTestResource.html Shows a runtime configuration with two ConnectionManagerForTests sections for test_db and desk_db. Each section must specify a unique resourceName and group MithraObjectConfiguration objects for that database. ```xml **** **** **** **** **** ... **** **** **** **** **** ... **** **** ``` -------------------------------- ### Check existence on one-to-many relationship Source: https://goldmansachs.github.io/reladomo/mithrafaq/ReladomoFaq.html Example of exists() on a one-to-many relationship (Product to TipsIndexRatio). It checks for at least one related record. ```java ProductFinder.tipsIndexRatios().exists() ``` -------------------------------- ### MithraTestSequence implementation Source: https://goldmansachs.github.io/reladomo/primaryKeyGenerator/PrimaryKeyGenerator.html Example implementation of the MithraSequence interface for the MithraTestSequence object. It adapts the getNextId and setNextId methods to the underlying nextValue attribute. ```java **public** **class** MithraTestSequence **extends** MithraTestSequenceAbstract **implements** MithraSequence { **public** **long** getNextId() { **return** **this**.getNextValue(); } **public** **void** setNextId(**long** nextValue) { **this**.setNextValue(nextValue); } } ``` -------------------------------- ### Ant target for MithraGraphGenerator Source: https://goldmansachs.github.io/reladomo/visualization/ReladomoVisualization.html An example Ant target to invoke the MithraGraphGenerator, which processes Reladomo XML metadata to produce a GraphML file. ```xml ``` -------------------------------- ### Create ProductInfo.xml Reladomo object definition Source: https://goldmansachs.github.io/reladomo/userguide/ReladomoTutorial.html Defines the ProductInfo Reladomo object with package, class name, default table, and three attributes. The productId attribute is marked as the primary key. This XML is the first file to create when setting up a Reladomo domain. ```xml **** ****com.gs.fw.common.mithra.test.domain**** ****ProductInfo**** ****PROD_INFO**** **** **** **** **** ``` -------------------------------- ### Set notification logging level to DEBUG Source: https://goldmansachs.github.io/reladomo/mithrafaq/ReladomoFaq.html Sets the notification logging level to DEBUG on each VM to get transparency into notification server activity. ```java com.gs.fw.common.mithra.notification ``` -------------------------------- ### Get all rows with FooFinder.all() Source: https://goldmansachs.github.io/reladomo/mithrafaq/ReladomoFaq.html Retrieves all rows from a database table by using FooFinder.all() as the operation. This translates a relational query with no WHERE clause to a Reladomo query. ```java FooList fooList = **new** FooList(FooFinder.all()) ``` -------------------------------- ### Mass delete with SwapPriceList.deleteAll() Source: https://goldmansachs.github.io/reladomo/presentations/mithraFeatures/ReladomoFeatures.xhtml Use this mass delete example to remove multiple rows in one operation. It builds an Operation by chaining equality conditions on sourceId, businessDate, and feedNumber, then creates a SwapPriceList and calls deleteAll(). The source reports that this implementation reduced deletion time from 562 seconds to 12 seconds for 65,583 rows. ```java Operation op = SwapPriceFinder.sourceId().eq( id ); op = op.and( SwapPriceFinder.businessDate().eq( busDate ) ); op = op.and( SwapPriceFinder.feedNumber().eq( feedNumber ) ); SwapPriceList priceList = **new** SwapPriceList(op); priceList.deleteAll(); ``` -------------------------------- ### Full Customer MithraObject Definition (Example 2.3) Source: https://goldmansachs.github.io/reladomo-kata/reladomo-tour-docs/tour-guide.html Complete XML definition for the Customer object, including attributes and the accounts relationship with reverseRelationshipName and relatedIsDependent. ```xml **** ****simplebank.domain**** ****Customer**** ****CUSTOMER**** **** **** **** **** **** this.customerId = CustomerAccount.customerId **** **** ``` -------------------------------- ### Full CustomerAccount MithraObject Definition (Example 2.4) Source: https://goldmansachs.github.io/reladomo-kata/reladomo-tour-docs/tour-guide.html Complete XML definition for the CustomerAccount object, including attributes for accountId, customerId, accountName, accountType, and balance. ```xml **** ****simplebank.domain**** ****CustomerAccount**** ****CUSTOMER_ACCOUNT**** **** **** **** **** **** **** ``` -------------------------------- ### Create a Customer with generated setters Source: https://goldmansachs.github.io/reladomo-kata/reladomo-tour-docs/tour-guide.html Creates a Customer object using the generated no-arg constructor and setter methods, then inserts it. The insert method is not shown here; the snippet only demonstrates object construction and attribute setting. ```java Customer mickey = **new** Customer(); mickey.setCustomerId(123); mickey.setFirstName(**"Mickey"**); mickey.setLastName(**"Mouse"**); ```