SpringOne Platform 2016: Bootiful Microservices in a Legacy Environment: Lessons Learned

Speaker: David Julia
Twitter: DavidJulia

 

In a Microservices Architecture

Services are cheap and fast to deploy and change independently.

Spring Boot

Simple and cheap to spin up a new microservice!
Autoconfiguration

Legacy Environment

An environment wherein many systems that are hard to change are in dire need of replacement or augmentation to meet business demands.

The importance of DDD in Legacy Environments

Domain-Driven Design is key! Lean on it!
Don’t couple your domain model to your legacy system’s models

You need to evolve to Microservices

appcontinuum.io

Succession Patterns

  • Strangler Application Pattern
  • Characterization tests – a vice

What’s the plan?

  • Identify behavior we need
  • “Sprout” a new class to hold behavior we want
  • Start moving behavior into that class
  • Sprout a component (JAR)

Premature Extraction

  • Extracting a Service too early can be costly
  • It’s easier to refactor the system with an in-process component
  • Only have to change things in one place

What did we just see

  • Started with a ball of mud
  • Identified/Extracted behavior into new classes
  • Packaged classes as JAR
  • Created a new service (strangler application)
  • Did all of this safely and with high confidence

Links

Simon Brown on Modular Monoliths
Working Effectively with Legacy Code

SpringOne Platform 2016: Testing with Spring 4.3, JUnit 5, and Beyond

Speaker: Sam Brannen
Twitter: @sam_brannen

Agenda

  • Spring Events App
  • Spring 4.3
  • JUnit 5
  • Spring 5

Spring Events App

The Spring Events App is a Spring boot powered web app using
Spring Boot 1.4, Spring Framework 5, JUnit 5.

Odds & Ends

  • JUnit 4.12+ required by the Spring TestContext framework (TCF)
  • Support for Primary transaction managers and data sources in TCF
  • @Sql and @Sqlgroup many now be used as meta-annotations:
    • to create custom composed annotations with attribute overrides
    • Same is true for many @Repeatable annotations in Core Spring
  • ReflectionTestUtils automatically unwraps proxies when setting/getting a field

Extending the Spring TextContext Framework

  • The getTestContext() method in TestContextManager is now public
  • New ContextCustomizer and ContextCustomizerFactory SPIs
    • Potentially replaces need for custom ContextLoader
    • Customize ApplicationContext after bean definitions are loaded but before context is refreshed
    • Registered globally by third parties via spring.factories mechanism
    • Enables Spring Boot Test Magic

New Features

  • SpringRunner alias for the SpringJUnit4ClassRunner
    >> @RunWith(SpringRunner.class)
  • @ContextConfiguration can be completely omitted…
    • if default XML or @Configuration is detected
    • Spring Boot test 1.4 even locates your @SpringBootApplication class
  • ApplicationContext cache is now bounded

Preparing for the Future

  • Testing Traits
    • Spring test annotations can be declared on interfaces
    • Combines nicely with Java 8 default methods and JUnit 5
  • Non-public @Transactional test methods: for use with JUnit 5 and TestNG
  • Non-public @BeforeTransaction and @AfterTransaction methods

MockMvc Improvements

  • Expectations on multi-value response headers: HeaderResultMatchers.stringValues(…)
  • Form data equest content (e.g., from a POST) now parsed and used to populate request params
  • Support for Custom HTTP verbs (e.g. WebDAV)
  • Improve Cookie support for HtmlUnit integration

MockMvc – Assert invoked Handler Method

New mock-like methodCall() assertion in HandlerResultMatchers: Assert the @Controller method invoked to handle the response:

    mockMvc.perform(get("/"))
    .andExpect(handler().methodCall(
     on(HomeController.class).showHomePage()));

MockMvc – JSON Prefixes

New support for stripping JSON prefixes from Responses. A prefix is used to prohibit JSON hijacking:

    mockMvc.perform(get("/account/42").accept(APPLICATION_JSON))
    .andExpect(jsonPath("$.pin")
    .prefix("&&enigma&&")
    ...

MockRestServiceServer Improvements

  • Expectations for form data in the request body
  • Specify expectation counts
    • Pass ExpectedCount to the expect() method
    • once(), manyTimes(), times(int), min(int), max(int), between(int, int)
    • verify() and reset() afterwards
  • Specify whether ordering should be ignored: invoke ignoreExpectOrder(true) on the MockResetServiceServerBuilder

JUnit 5: Impetus for Change

  • JUnit 4.0 was released a decade ago
  • Modularity -> big ball of mud (i.e., only THE junit.jar)
  • Test Discovery and execution -> tightly coupled
  • Extensibility -> lot of room for improvement
  • Java 8 support

JUnit 4 Runner API

  • Very Powerful
  • You can do anything
  • But you cannot combine Runners
  • Parameterized + SpringJUnit4ClassRunner -> no way

JUnit 4… Rules… are meant to be broken

  • JUnit 4.7: MethodRule -> @Rule
  • JUnit 4.9: TestRule -> @Rule/@ClassRule

JUnit Lambda

  • Initiated by Johannes Link and Marc Philipp
  • Later joined by Matthias Merdes, Stefan Bechtold, and Sam Brannen

JUnit 5 – Roadmap

  • Prototype – December 2015
  • Alpha – February 2016
  • M1 & M2 – July 2016
  • M3, M4, RC1 – Fall 2016
  • GA – End of 2016… maybe

JUnit 5 – In a Nutshell

  • Modular
  • Extensible
  • Modern
  • Forward & Backward Compatible
    • JUnit Platform supports JUnit 3.8, 4 and 5
    • New testing frameworks can be run with JUnit 4 infrastructure:
      @RunWith(JUnitPlatform.class)

JUnit 5 = Platform + Jupiter + Vintage

  • JUnit Platform 1.0.0
    • Foundation for launching testing frameworks on the JVM
    • Launcher and TestEngine APIs
    • ConsoleLauncher, Gradle Plugin, Maven Surefire provider
  • JUnit Jupiter 5.0.0: New programming model and extension model for JUnit 5
  • JUnit Vintage 4.12.0: TestEngine for running old stuff

Launcher API

  • Used by IDEs and build tools to launch the framework
  • Central API for discovering and executing tests via one or more engines
  • LauncherDiscoveryRequest: Selectors and filters
  • Feedback provided via the TestExecutionListener API

TestEngine API

  • aka, Runner in JUnit 4
  • Test engine discovers and executes tests for a particular programming model
  • Automatic registration via Java’s ServiceLoader mechanism
  • JupiterTestEngine
  • VintageTestEngine
  • Implement your own…

Extension APIs

  • BeforeAllCallback
  • BeforeEachCallback
  • BeforeTestExecutionCallback
  • AfterTestExecutionCallback
  • AfterEachCallback
  • AfterAllCallback
  • ContainerExecutionCondition & TestExecutionCondition
  • TestInstancePostProcessor
  • ParameterResolver
  • TestExecutionExceptionHandler

JUnit 5 – Programming Model

org.junit.jupiter.api

  • Annotations & Meta-annotations
  • Assertions & Assumptions
  • Custom Display Names
  • Visibility
  • Tagging
  • Conditional Test Execution
  • DI for Constructors and methods
  • Lambda Expressions and method references
  • Interface default methods
  • Nested test classes
  • Dynamic Tests

Annotations

  • @Test / @TestFactory
  • @BeforeAll / @AfterAll
  • @BeforeEach / @AfterEach
  • @DisplayName
  • @Tag
  • @Disabled
  • @Nested

Assertions

org.junit.jupiter.api.Assertions

  • Limited set of core assertions
  • assertThrows() and expectThrows()
  • assertTimeout()
  • assertAll()

SpringOne Platform 2016: Intro to Spring Boot

Speaker: Eddú Meléndez
Twitter: @EdduMelendez

 

Spring Ecosystem: The Spring Framework

  • Spring Social
  • Spring Web Services
  • Spring Integration
  • Spring AMQP
  • Spring Hatecas
  • Spring Mobile
  • Spring Security
  • Spring Data
  • Spring Batch

Spring Boot is not ingredients but the whole cake

XML Config > Java Config > Spring Boot Configuration

spring.datasource.username=sa
spring.datasource.password=password

Why Spring Boot?

    • Convention over Configuration
    • Provide dependency Management
    • Auto-configuration
    • Starter Dependencies
    • Actuator

Demo

start.spring.io

or via the command line:

curl https://start.spring.io

or using Spring CLI:

spring run appname

Properties

Defining properties in Spring:

@ConfigurationProperties(prefix="conference")
public class ConferenceProperties {
    ...
}

In application.properties:

conference.name=Spring One Platform
conference.location=Aria Hotel, Las Vegas

Spring Actuator

Provides various health and configuration metrics about your Spring application.

        • /health
        • /metrics
        • /env

Spring Boot Starter Security

Default username is ‘user’ and password is generated

Of course, can be configured:

@Configuration
public class SecurityConfig extends GlobalAuthenticationConfigurerAdapter {
    @Override
    public void init(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication...
    }
}

SpringOne Platform 2016: Testing Spring Boot Applications

Speaker: Phil Webb, @phillip_webb
Project: github.com/philwebb/testing-spring-boot-applications

Spring requires no-arg constructors, but there’s no reason that these have to be public: make them protected if it makes sense.

You need tests for:

  1. Domain Layer
  2. Service Layer
  3. Web Layer

@RunWith(SpringRunner.class)

Service Layer Testing

@JSonTest to test JSON format
@MockBean to mock a dependency

Web Layer testing

Test class annotation:
@WebMvcTest


@Autowired
private MockMvc mvc

@MockBean

@AutoConfigureMockMvc
@AutoConfigureTestDatabase

SpringOne Platform 2016: Wall St. Derivative Risk Solutions Using Apache Geode

Speaker: Andre Langevin, CIBC
Speaker: Mike Stolz, Pivotal
White Paper: http://pivotal.io/building-wall-street-risk-applications
Geode: http://geode.incubator.apache.org

GemFire is the commercial offering of Geode

Design

  • Input: Trades
  • Input: Market Data
  • Output: Risk
  • Where the Magic Happens: Risk Calculations
  • Geode is the backbone infrastructure

A Crash Course in Wall Street

  • Big Wall Street firms have “FICC” trading business organized by market
    • Each business will trade “cash” and derivative products, but traders specialize in one or the other
    • There may be a team of traders working to trade a single product
  • Trading systems are product specific and often highly specialized
  • Managing these businesses requires a consolidated view of risk

Calculating Risk

  • What is the “risk” that we are trying to measure?
  • Markets are represented using curves
  • Consistency is paramount

Technology Solutions that Work Badly

  • The easiest thing to do is just book all your trades using one trading system
  • How about booking all of the hedges into the primary trading system?
  • How about adding up all of the risk from each trading system into a report

Designing and Naming Data Objects

  • The trade data model serves 2 distinct purposes
  • Market data should follow the calculation design
  • Use “dot” notation to give business-friendly keys to object (i.e., USD.LIBOR.3M)

Region Design

  • Trade and market data regions
  • Typically a curve embeds a list for rates — leave it denormalized if rates are updated slowly
  • Computational results and aggregation
  • Regions: Rates, Trades, Curves, Built Curves, FX, Trade Risk, Risks, Agg

Placing Regions on the Cluster

  • Region placement optimizes the solution’s performance
  • Partition the trades regions to balance the cluster
  • Partition or replicate market data to optimize computations

PDX Integration Glue

  • PDX serialization is an effective cross-language bridge
  • Structure PDX objects to optimize performance
  • JSON is a good message format

Getting Trade Data into Geode

  • Message formats vary by product type
  • Broker messages in an application server
  • Trade data capture is transactional: Best practive is to make end-to-end process a transaction, but may need to split into two legs based on source of messages

Getting Market Data into Geode

  • Market data feeds have many proprietary formats
  • Market data is often exceptionally fast moving
  • Market data can also be very slow moving: i.e., LIBOR
  • Conflate fast market data by sampling
  • Gate market data into batches

Crunching Numbers on a Shared Grid

  • Most trading firms have a proprietary math library
  • Pushing Geode events to an external compute grid: Asynchronous Event Queue (AEQ)
  • Caching locally on the grid to accelerate performance: Wildcards on keys

Crunching Numbers Inside Geode

  • Running the math inside Geode is dramatically faster
  • Using the Geode grid as a compute grid
  • Using cache listeners to propagate valuation events

Ticking Risk Views

  • Roll-your-own client applications to view ticking risk
  • Integrating packaged products: ION Enterprise Risk, Armanta Theatre, Active Pivot…
  • The Traders always want spreadsheets: Write an Excel plug-in

SpringOne Platform 2016: Building Applications with Angular JS and Spring Security

Speaker: Dave Syer, @david_syer

Agenda

  • Real quick intro to Spring Security, Spring Session, Angular JS
  • Focus on features to build secure, modern, single-page applications
  • High level view of sample apps presented in tutorial (from blog series)
  • More Details look at some features of the apps

Most valuable links

Spring Security

  • Generic Filter based solution for Servlet applications
  • Authentication (a.k.a. identity) and Authorization (a.k.a. access decisions)
  • OAuth2 module useful for SSO and token-based API authentication
  • lots of other features
  • http://projects.spring.io/spring-security

Angular JS

  • Javascript Framework
  • “Magic” binding (dependency injection and MVC)
  • Has a lot of traction in the enterprise
  • Nothing about the architecture of the apps presented here requires Angular JS
  • Really basic usage in sample, but representative

Security Features in Modern Browsers

  • HTTP Basic
  • X.509 authentication
  • Kerberos
  • Kerberos
  • Cookies
  • CORS (Common Origin Resource Sharing)
  • HSTS (HTTP Strict Transport Security
  • CSP (Content Security Policy)

Sub-text: “use them, they’re reliable and free…”

Spring Session

  • Not tied to Spring Security, but works well with it
  • Easy, declarative, distributed sessions
  • Redis works out of the box, other backends easy to add
  • Servlet Filter
  • http://cloud.spring.io

Add HTTP Basic Security

  • Add spring-boot-starter-security dependency
  • Set security.user.password=password to application.properties
  • Add SecurityConfiguration extends WebSecurityConfigurerAdapter
  • Suppress the Browser Dialog by adding X-Requested-With XmlHttpRequest in HTTP request

Cross Site Request Forgery (CSRF)

  • Spring Security and Angular JS both have good support for CSRF protection
  • HTTP Request Header: X-CSRF-TOKEN

CORS

  • Use @CrossOrigin on your @RequestMapping and this: http.cors()
  • Tip: there is also CorsUtils::isCorsRequest method you can use in a request matcher

Spring MVC and JSTL MessageSource Configuration

I’ve been working on a new web application over the last month whenever I can find some spare time.   I had initially started the project using Grails, but I had difficulty getting past the scaffolding.   Besides, my reading seems to always come back to Grails performance issues so I figured I’d just start with a tried & true Java Enterprise stack:  Spring, Hibernate, Spring MVC, and MySQL.

I spent the last few weeks dealing with the model, DAO, service, and controller layers.   I’m aiming for a solid RESTful API consuming and producing JSON from the onset.  I got all that to work seemingly well and am now actually ready to focus on views so I wrote my first JSP in about 10 years yesterday:

    <%@ include file="taglibs.jsp"%>
    <head>
        <title><fmt:message key="home.title"/></title>
    </head>
    <body class="home">
        <fmt:message key="home.heading"/>
    </body>

Now in my maven /src/main/resources directory, I have a message.properties file containing the following:

    home.properties=Home
    home.heading=Hello World!

Finally, I added the following to my MVC Configuration file (I’m using JavaConfig as opposed to the old school Spring XML):

    @Bean
    public MessageSource getMessageSource() {
        ResourceBundleMessageSource source = new ResourceBundleMessageSource();
        source.setBasename("messages");
        return source;
    }

Not really any rocket science here, folks… This is pretty much standard based on the Spring documentation and about half a dozen blog entries.   The only difference with my configuration and what I found online was that the MessageSource was being configured using XML.

I spent several hours trying to get this to work but the view would render with ???home.title??? and ???home.heading??? and I couldn’t for the life of me figure out what the problem was.   I know that the bean was getting instantiated because I added a breakpoint there…   Finally I tried actually retrieving the MessageSource bean in the controller from the ApplicationContext.   Instead, I got a big fat exception that the bean was not found.    So I changed my configuration to retrieve the bean by name instead of by class:

    @Bean(name="messageSource")
    public MessageSource getMessageSource() {
         ResourceBundleMessageSource source = new ResourceBundleMessageSource():
         source.setBasename("messages"):
         return source;
     }

Just like magic, the JSP view now rendered just fine! Simply naming the bean ‘messageSource’ resolved a problem I had been tackling for several hours. I realize this blog doesn’t have an insane amount of traffic, but hopefully this will help somebody who runs into the same problem I did.

 

TSSJS2011: How to Reap the Benefits of Agile-Based TDD

I attended a breakout session on jQuery right after lunch, but I didn’t have my laptop up and, honestly, it was a pretty high-level presentation of jQuery in any case.   The technology certainly looks promising and I’ll have to find a way to play with it one of these days.   Then again, I’m still trying to play with Scala and Mule, technologies I heard and read about after last year’s TSSJS.   Aaaah…. where does the time go?

Agile based TDD sounds like a good session.   As much as I keep wanting to move to TDD, I have a really difficult time doing so.   Hopefully the more exposed I am to it, the easier it’ll become to actually use the methodology.

What is TDD?
Test-Driven Development is a software development process.

The TDD Process:
1.  Write a failing test for the target behavior
2.  Implement the behavior as simple as possible to get the test to pass
3.  Refactor the implementation

TDD is a Design Activity

TDD treats Tests as VIP Artifacts:  You need to treat your tests as first-class citizens

TDD is an “Agile” Practice:
1.  Working software is the primary measure of progress
2.  Continuous Attention to technical excellence and good design enhances agility
3.  Welcome changing requirements, even late in development

Types of Tests:
1.  Unit Testing: Verification of Design
2.  Acceptance Testing:  Verification of Features

What is a Unit Test?
Exercises a small testable piece of software
Tests a specific object behavior in isolation
Assumes that external dependencies work according to their contracts
Defines the assumptions that can be made of the target unitHow is unit test independent of its dependencies?  Mock Objects

Tools and Frameworks

JUnit
Openpojo:  a framework for validating that POJOs are adhering to a standard contract
Mockito:  Mocking Framework – Declare dependencies with @org.mockito.Mock

The Benefits of TDD

Test-Driven Development improves Design

SOLID Design
* Single responsibility principle: Can do one thing really well, loosely coupled
* Open/close Principle: Encapsulation – What, not how?
* Liskov substitution principle: Contract  first Design.  Avoid inheritance unless “is a” …
* Interface Segregation Principle: Interface clients should only depend on methods they need
* Dependency Inversion Principle: Depend on Abstractions instead of mocking

TDD Follows Law of Demeter

TDD avoids Static Helper Classes:  Procedural programming, not OO programming.

TDD Measures Progress, provides Documentation, and provides code coverage

How to Make it Work

* Flip Your Perspective – become a user, not a developer
* Always See Your Test Fail – make sure your tests have clear messages
* Listen to Your Tests – Urge to share test fixture state, setup, … => need to refactor
* Use an Interface Driven Approach
* Learn it well – TDD by Kent Beck

KATA

TDD Kata – Exercise in coding, refactoring and test-first, that you should apply daily for at least 15 minutes.  -Roy Osherove

http://www.osherove.com/tdd-kata-1/

TSSJS2011: Do You Really Know Class Loaders?

I’m back at The Server Side Java Symposium this year and this is the first breakout session I’m attending.   I think I’ve got good knowledge of ClassLoaders and Java Reflection API, but we’ll see if Jevgeni Kabanov, the speaker, can enlighten me with some new nuggets of knowledge.   He’s Founder & CTO of ZeroTurnaround, a company I know next to nothing about, although I have heard of JRebel, one of their products.   Anyway, enough background info… Let’s jump into the meat of the presentation.

Basics

public class A {
    public void do() {
        B b = new B();
        b.do():
    }
}
Instantiating Object B causes the following:  A.class.getClassLoader().loadClass("B");

Problems & Solutions

1. Class Not Found
You build some code and get a NoClassDefFound exception when deploying and trying to run the servlet.   How do we find out what the problem is?

Some solutions:
* IDE Class Lookup
* find *.jar -exec jar -tf ‘{}’ \; | grep MyClass
* URLClassLoader.getURLs()

2. Wrong Class Found
What if you get a NoSuchMethodError?  What’s happening there?  Well, the Class is found, but there’s something wrong with the class.

Solution:
* Get ClassLoader().getResource(Util2.class.replace(‘.’,’/’) + “.class” to find out where the ClassLoader is getting the class.  Then you can use javap -private Util2 to inspect the contents of the file.

3. More than One Class Found
That error will typically occur if 2 different ClassLoaders are used and find different classes for the same name.   They are not the same.

Helpful:  -verbose:class, as well as ClassLoader.getResource() to identify the different classes.

Leaking ClassLoaders

If a Class has a reference to its ClassLoader, that object has a reference to all of its classes.    To leak a ClassLoader, it’s enough to leak just one object loaded by that ClassLoader.

Hierarchy is not enough?

* Isolation: Difference versions of the same library
* Performance: Class lookup is very slow
* Restricted: Why can’t siblings see each other’s classes?
* OSGI, JBoss, NetBeans and others implement a different system

Follow the speaker on Twitter: @ekabanov

Adding a new objective to Calypso Forward Ladder

I’ve been spending the last 6 weeks configuring the Forward Ladder in Calypso 11 in order to get a real-time view into FX risk from Opics.  While I actually did some work on the Forward Ladder analysis when I was back at Calypso, they did a complete rewrite for version 11 and I must say that, while I did encounter a few issues, it is well thought out and quite extensible.  As such, I thought I’d share how easy it is to plug in a new objective in the forward ladder.

The request was to display the discount factor (df, for short) which is unfortunately not available in the new ForwardLadder analysis.   While it was a column in one of the earlier incantations of the analysis (i.e., FwdLadder), it seems to have disappeared in this latest version.   We could have of course asked for a P6 enhancement request, but that probably means we’d have had to roll this out next year as opposed to this year, so that was a no go.   Digging into the code, I came across the Forward Ladder Registry, a class that allows you to plug in and/or modify the objectives and flow generation extremely easily.

The ForwardLadderRegistry class actually reads the configuration from an XML file included in the resources.jar called com/calypso/tk/risk/ForwardLadderGeneratorMappings.xml.  Here’s a snippet from that file:

<registry>
    <global>
        <objectiveGenerators>
            <generator>
                <objectiveClass>com.calypso.tk.risk.forwardladder.objective.ForwardLadderObjectiveCore</objectiveClass>
                <generatorClass>com.calypso.tk.risk.forwardladder.generator.DefaultCoreGenerator</generatorClass>
            </generator>
            <generator>
                <objectiveClass>com.calypso.tk.risk.forwardladder.objective.ForwardLadderObjectiveCash</objectiveClass>
                <generatorClass>com.calypso.tk.risk.forwardladder.generator.DefaultCashFlowAmountCashGenerator</generatorClass>
            </generator>
            ...
        </objectiveGenerators>
    </global>
    ...
</registry>

I decided to create a new objective called MarketData in order to bring in the df, as requested by the users.   Thus, I added the following lines to the xml file:

            ...
            <generator>
                <objectiveClass>com.myco.tk.risk.forwardladder.objective.ForwardLadderObjectiveMarketData</objectiveClass>
                <generatorClass>com.myco.tk.risk.forwardladder.generator.DefaultMarketDataGenerator</generatorClass>
            </generator>
            ...

That’s easy enough, right?   The code for the ForwardLadderObjectiveMarketData is trivial enough and you can easily implement it based on one of the other objectives supplied by Calypso.   The meat & bones, however, resides in the DefaultMarketDataGenerator which actually implements the ForwardLadderObjectiveGeneratorI interface.  (Incidentally, I’m not quite sure why Calypso forces you to implement 2 interfaces here.   I think one interface could easily have described the contract for both the objective metadata and the actual implementation!  Go figure…)

Here’s what the code looks like to display the discount factor:

public class DefaultMarketDataGenerator implements ForwardLadderObjectiveGeneratorI {
...
public void populateObjectiveData(ForwardLadderObjectiveI objective, FlowGenerationContextI context,
List<ForwardLadderFlowItem> flows) { Trade trade = context.getTrade(); PricingEnvBasedFlowGenerationContext peContext = (PricingEnvBasedFlowGenerationContext)context; for (ForwardLadderFlowItem flow : flows) { for (ColumnMetaData metaData : objective.getObjectiveColumnMetaData(context.getParams())) { String dataName = metaData.getName(); if (ForwardLadderObjectiveMarketData.CURRENCY_DF.equals(dataName)) { CashFlow cf = flow.getCashFlow(); String ccy = cf.getCurrency(); CurveZero curve = peContext.getPricingEnv().getPricerConfig().getDiscountZeroCurve(ccy); double df = 1.; try { df = curve.getDF(trade.getSettleDate(), QuoteSet.MID); Amount dfDV = new Amount(df, ForwardLadderAnalysisUtil.DEFAULT_CONVERSION_RATE_ROUNDING); ForwardLadderObjectiveData data = new ForwardLadderObjectiveData(metaData, dfDV); flow.setObjectiveData(dataName, data); } catch (Throwable t) { Log.error(LOG_CATEGORY, t); } } } } }
}

That just about does it, believe it or not!   The only thing is you’ll have to tweak one more resource bundle file or the ParamViewer will choke when trying to add the new objective.   Look for a file called com/calypso/bundles/apps/forwardladder/ForwardLadderObjectives.properties in the resources.jar and add the following properties at the end of that file:

objective.displayname.MarketData=Market Data
objective.help.MarketData=

As long as your classes and modified resource files come before Calypso’s in your classpath, you’ll be able to add this new objective to your Forward Ladder.