-
Notifications
You must be signed in to change notification settings - Fork 0
Type conversions
In an effort to minimize boilerplate, Rapier provides automatic type conversion as part of its core feature set. This allows users to provision configuration data in whatever data type they require, as opposed to having to write a conversion factory method every time.
The following Dagger component uses type conversion to provision an environment variable as a long
:
@Component(modules = RapierExampleComponentEnvironmentVariableModule.class)
public interface ExampleComponent {
/**
* Get timeout in milliseconds from environment variable TIMEOUT, or use the
* default of 30000 if not present
*/
@EnvironmentVariable(value="TIMEOUT", defaultValue="30000")
public long timeout();
}
Environment variables are provided as a String
by default. This method requests the environment variable TIMEOUT
as a long
, which causes Rapier to generate a @Provides
method for the TIMEOUT
environment variable as a long
.
Most Rapier modules provide their configuration data as a String
by default. These modules generally support the following type conversions:
- Primitives (i.e.,
byte
,short
,int
,long
,char
,float
,double
,boolean
) - Boxed primitives (i.e.,
Byte
,Short
,Integer
,Long
,Character
,Float
,Double
,Boolean
) - Types
T
with a methodpublic static T fromString(String)
. In addition to custom user types, this adds support for the following built-in JRE types:java.util.UUID
- Types
T
with a methodpublic static T valueOf(String)
- Types
T
with a constructorpublic T(String)
. In addition to custom user types, this adds support for the following built-in JRE types:java.net.URL
java.net.URI
java.io.File
java.math.BigDecimal
java.math.BigInteger
Some Rapier modules also provide their configuration data as a List<String>
. These modules generally support the following type conversions:
- List types
java.util.List<T>
for any reference scalar typeT
with a conversion fromString
- Types
T
with a methodpublic static T valueOf(List<String>)
- Types
T
with a constructorpublic T(List<String>)
If the converted parameter is not nullable and the conversion results in a null
value, then an IllegalStateException
is thrown.
If the conversion results in an exception of any type, then a IllegalArgumentException
is thrown with the original exception as the cause.
Users can choose to perform manual Dagger conversions instead of relying on the standard Rapier-generated conversions.
For example, when using the Rapier environment variable module, Rapier automatically generates a standard conversion for the TIMEOUT environment variable to the requested int type for the specified component:
@Component(modules = RapierExampleComponentEnvironmentVariableModule.class)
public interface ExampleComponent {
@EnvironmentVariable(value="TIMEOUT", defaultValue="30000")
public int timeout();
}
/**
* Rapier would generate code like this from the injection site in
* ExampleComponent.
*/
@Module
public class RapierExampleComponentEnvironmentVariableModule {
@Provides
@EnvironmentVariable(value="TIMEOUT", defaultValue="30000")
public String provideEnvironmentVariableTimeoutAsString() {
final String result=env.get("TIMEOUT");
if(result == null)
return "30000";
return result;
}
@Provides
@EnvironmentVariable(value="TIMEOUT", defaultValue="30000")
public int provideEnvironmentVariableTimeoutAsInt(
@EnvironmentVariable(value="TIMEOUT", defaultValue="30000")
String value) {
return Integer.parseInt(value);
}
}
Users who prefer to handle the conversion manually can use the following approach instead:
@Component(modules = {
RapierExampleComponentEnvironmentVariableModule.class,
ExampleModule.class
})
public interface ExampleComponent {
/**
* Users can use whatever qualifier they like, or no qualifier.
* This is just for clarity in this example.
*/
@Named("timeout")
public int timeout();
}
/**
* The user performs the conversion themselves with this module.
*/
@Module
public class ExampleModule {
@Provides
public int provideTimeoutAsInt(
@EnvironmentVariable(value="TIMEOUT", defaultValue="30000")
String value) {
final int result=Integer.parseInt(value);
// Custom validation logic here, or whatever
return result;
}
}
/**
* Rapier would generate code like this from the injection site in
* ExampleModule.
*/
@Module
public class RapierExampleComponentEnvironmentVariableModule {
@Provides
@EnvironmentVariable(value="TIMEOUT", defaultValue="30000")
public String provideEnvironmentVariableTimeoutAsString() {
final String result=env.get("TIMEOUT");
if(result == null)
return "30000";
return result;
}
}
The main difference between the two approaches lies in how the @EnvironmentVariable
annotation is used. The first example uses the @EnvironmentVariable
annotation on the public int timeout()
method, whereas the second example uses the @EnvironmentVariable
annotation on the parameter of the public int provisionTimeoutAsInt(String)
method.
This flexibility allows users to leverage Rapier to generate code for a default or convenient representation while providing their own modules with factory methods to handle the conversion instead of being forced to use the standard conversion. This approach works consistently across all Rapier modules.