Although his example describes how to create a sandbox and production version of a service using symbols, this method can be used for various other scenarios.
Scenario: you are developing a shopping cart and want to test your app against the sandbox PayPal NVPServer, without having to hard-code the variables into your implementation:
Note: This examples assumes you can read symbols from properties files (see Tapestry5HowToReadSymbolsFromPropertiesFile). Also, it uses the PayPal NVP library.
public class AppModule {
// make configuration from 'paypal.properties' on the classpath available as symbols
public PropertiesFileSymbolProvider buildPayPalPropertiesFileSymbolProvider(Logger logger) {
return new PropertiesFileSymbolProvider(logger, "paypal.properties", true);
}
public static void contributeSymbolSource(OrderedConfiguration<SymbolProvider> configuration,
@InjectService("PayPalPropertiesFileSymbolProvider") SymbolProvider payPalPropertiesFileSymbolProvider) {
configuration.add("PayPalPropertiesFile", payPalPropertiesFileSymbolProvider, "after:SystemProperties", "before:ApplicationDefaults");
}
}we have a properties file that stores our credentials for the different services (src/main/resources/paypal.properties):
#paypal.api.endpoint=live paypal.api.endpoint=sandbox paypal.api.sandbox.username=my_sandbox_username@email.com paypal.api.sandbox.password=my_sandbox_password@email.com paypal.api.sandbox.signature=SANDBOX_SIGNATURE paypal.api.live.username=my_live_username@email.com paypal.api.live.password=my_live_username@email.com paypal.api.live.signature=LIVE_SIGNATURE
Our PayPalNVPService Implementation looks something like this:
public class PayPalNVPService {
/* set user - these are your credentials from paypal */
private Profile user;
private Environment environment;
public PayPalNVPService(Environment environment, String apiUsername, String apiPassword, String signature) {
this.environment = environment;
user = new BaseProfile.Builder(apiUsername, apiPassword).signature(signature).build();
}
public boolean SetExpressCheckout(String returnURL, String cancelURL, ... ) {
/* create new instance of paypal nvp */
PayPal pp = new PayPal(user, environment);
...
}
}Ideally we want to be able to do something like @Inject @Symbol("paypal.api.${paypal.api.endpoint}.username") String userName. However this doesn't work, as only @Value and @InjectService allow Symbol substitution. Thus, we will have to to create a new symbol:
public class AppModule {
public static void contributeApplicationDefaults(MappedConfiguration<String, String> configuration) {
configuration.add("PayPalNVPService", "paypal.nvp.${paypal.api.endpoint}");
}
}And now we'll just need to create two different services, based on the different credentials:
public class AppModule {
@ServiceId("paypal.nvp.sandbox")
public static PayPalNVPService buildPayPalNVPSandboxService(
@Inject @Symbol(value="paypal.api.sandbox.username") String apiUsername,
@Inject @Symbol(value="paypal.api.sandbox.password") String apiPassword,
@Inject @Symbol(value="paypal.api.sandbox.signature") String signature) {
return new PayPalNVPService(Environment.SANDBOX, apiUsername, apiPassword, signature);
}
@ServiceId("paypal.nvp.live")
public static PayPalNVPService buildPayPalNVPLiveService(
@Inject @Symbol(value="paypal.api.live.username") String apiUsername,
@Inject @Symbol(value="paypal.api.live.password") String apiPassword,
@Inject @Symbol(value="paypal.api.live.signature") String signature) {
return new PayPalNVPService(Environment.LIVE, apiUsername, apiPassword, signature);
}
}(If anyone knows how to evaluate symbols inside contributeApplicationDefaults, please let me know as I would prefer to just simply create 3 new symbols for username, password and signature and then in inject the symbols into the service implementation and used auto-building.)
And lastly inject the service into our page. Notice how we have to evaluate the PayPalNVPService symbol to get the actual service id:
public class ViewCart {
@InjectService("${PayPalNVPService}")
private PayPalNVPService paypalService;
public void onActionFromCheckoutWithPayPal() {
boolean success = paypalService.SetExpressCheckout("http://localhost:8080/website/checkout/revieworder", "http://localhost:8080/website/viewcart", ...);
...
}
}