I really like the addition of records in Java 14, at least as a preview feature, as it helps to reduce my need to use lombok for simple, immutable "data holders". But I'm having an issue with the implementation of nullable components. I'm trying to avoid returning null in my codebase to indicate that a value might not be present. Therefore I currently often use something like the following pattern with lombok.
#Value
public class MyClass {
String id;
#Nullable String value;
Optional<String> getValue() { // overwrite the generated getter
return Optional.ofNullable(this.value);
}
}
When I try the same pattern now with records, this is not allowed stating incorrect component accessor return type.
record MyRecord (String id, #Nullable String value){
Optional<String> value(){
return Optional.ofNullable(this.value);
}
}
Since I thought the usage of Optionals as return types is now preferred, I'm really wondering why this restriction is in place. Is my understanding of the usage wrong? How can I achieve the same, without adding another accessor with another signature which does not hide the default one? Should Optional not be used in this case at all?
A record comprises attributes that primarily define its state. The derivation of the accessors, constructors, etc. is completely based on this state of the records.
Now in your example, the state of the attribute value is null, hence the access using the default implementation ends up providing the true state. To provide customized access to this attribute you are instead looking for an overridden API that wraps the actual state and further provides an Optional return type.
Of course, as you mentioned one of the ways to deal with it would be to have a custom implementation included in the record definition itself
record MyClass(String id, String value) {
Optional<String> getValue() {
return Optional.ofNullable(value());
}
}
Alternatively, you could decouple the read and write APIs from the data carrier in a separate class and pass on the record instance to them for custom accesses.
The most relevant quote from JEP 384: Records that I found would be(formatting mine):
A record declares its state -- the group of variables -- and commits
to an API that matches that state. This means that records give up a
freedom that classes usually enjoy -- the ability to decouple a
class's API from its internal representation -- but in return, records
become significantly more concise.
Due to restrictions placed on records, namely that canonical constructor type needs to match accessor type, a pragmatic way to use Optional with records would be to define it as a property type:
record MyRecord (String id, Optional<String> value){
}
A point has been made that this is problematic due to the fact that null might be passed as a value to the constructor. This can be solved by forbidding such MyRecord invariants through canonical constructor:
record MyRecord(String id, Optional<String> value) {
MyRecord(String id, Optional<String> value) {
this.id = id;
this.value = Objects.requireNonNull(value);
}
}
In practice most common libraries or frameworks (e.g. Jackson, Spring) have support for recognizing Optional type and translating null into Optional.empty() automatically so whether this is an issue that needs to be tackled in your particular instance depends on context. I recommend researching support for Optional in your codebase before cluttering your code possibly unnecessary.
Credits go to Holger! I really like his proposed way of questioning the actual need of null. Thus with a short example, I wanted to give his approach a bit more space, even if a bit convoluted for this use-case.
interface ConversionResult<T> {
String raw();
default Optional<T> value(){
return Optional.empty();
}
default Optional<String> error(){
return Optional.empty();
}
default void ifOk(Consumer<T> okAction) {
value().ifPresent(okAction);
}
default void okOrError(Consumer<T> okAction, Consumer<String> errorAction){
value().ifPresent(okAction);
error().ifPresent(errorAction);
}
static ConversionResult<LocalDate> ofDate(String raw, String pattern){
try {
var value = LocalDate.parse(raw, DateTimeFormatter.ofPattern(pattern));
return new Ok<>(raw, value);
} catch (Exception e){
var error = String.format("Invalid date value '%s'. Expected pattern '%s'.", raw, pattern);
return new Error<>(raw, error);
}
}
// more conversion operations
}
record Ok<T>(String raw, T actualValue) implements ConversionResult<T> {
public Optional<T> value(){
return Optional.of(actualValue);
}
}
record Error<T>(String raw, String actualError) implements ConversionResult<T> {
public Optional<String> error(){
return Optional.of(actualError);
}
}
Usage would be something like
var okConv = ConversionResult.ofDate("12.03.2020", "dd.MM.yyyy");
okConv.okOrError(
v -> System.out.println("SUCCESS: "+v),
e -> System.err.println("FAILURE: "+e)
);
System.out.println(okConv);
System.out.println();
var failedConv = ConversionResult.ofDate("12.03.2020", "yyyy-MM-dd");
failedConv.okOrError(
v -> System.out.println("SUCCESS: "+v),
e -> System.err.println("FAILURE: "+e)
);
System.out.println(failedConv);
which leads to the following output...
SUCCESS: 2020-03-12
Ok[raw=12.03.2020, actualValue=2020-03-12]
FAILURE: Invalid date value '12.03.2020'. Expected pattern 'yyyy-MM-dd'.
Error[raw=12.03.2020, actualError=Invalid date value '12.03.2020'. Expected pattern 'yyyy-MM-dd'.]
The only minor issue is that the toString prints now the actual... variants. And of course we do not NEED to use records for this.
Don't have the rep to comment, but I just wanted to point out that you've essentially reinvented the Either datatype. https://hackage.haskell.org/package/base-4.14.0.0/docs/Data-Either.html or https://www.scala-lang.org/api/2.9.3/scala/Either.html. I find Try, Either, and Validation to be incredibly useful for parsing and there are a few java libraries with this functionality that I use: https://github.com/aol/cyclops/tree/master/cyclops and https://www.vavr.io/vavr-docs/#_either.
Unfortunately, I think your main question is still open (and I'd be interested in finding an answer).
doing something like
RecordA(String a)
RecordAandB(String a, Integer b)
to deal with an immutable data carrier with a null b seems bad, but wrapping recordA(String a, Integer b) to have an Optional getB somewhere else seems contra-productive. There's almost no point to the record class then and I think the lombok #Value is still the best answer. I'm just concerned that it won't play well with deconstruction for pattern matching.
Related
I have the following in a working test:
when(client.callApi(anyString(), isA(Office.class))).thenReturn(responseOne);
Note that client is a Mock of class Client.
I want to change "isA(Office.class)" to tell it to match where the "id" property of an Office instance is "123L". How can I specify that I want a specific argument value in the method of a mocked object?
Edit: Not a duplicate because I'm trying to use it on a "when" and the linked question (and other resources I've found) are using ArgumentCaptor and ArgumentMatcher on "verify" and "assert". I'm thinking I can't actually do what I'm trying and will try out another way. Of course, I'm willing to be shown otherwise.
Reopening as requested, but the solution (use an ArgumentMatcher) is identical to the one in the linked answer. Naturally, you can't use an ArgumentCaptor when stubbing, but everything else is the same.
class OfficeWithId implements ArgumentMatcher<Office> {
long id;
OfficeWithId(long id) {
this.id = id;
}
#Override public boolean matches(Office office) {
return office.id == id;
}
#Override public String toString() {
return "[Office with id " + id + "]";
}
}
when(client.callApi(anyString(), argThat(new IsOfficeWithId(123L)))
.thenReturn(responseOne);
Because ArgumentMatcher has a single method, you can even make it a lambda in Java 8:
when(client.callApi(anyString(), argThat(office -> office.id == 123L))
.thenReturn(responseOne);
If you're already using Hamcrest, you can adapt a Hamcrest matcher using MockitoHamcrest.argThat, or use the built-in hasProperty:
when(client.callApi(
anyString(),
MockitoHamcrest.argThat(
hasProperty("id", equalTo(123L)))))
.thenReturn(responseOne);
I ended up going with "eq". This was ok in this case because the objects are pretty simple. First I created an object that is the same as what I expect to get back.
Office officeExpected = new Office();
officeExpected.setId(22L);
Then my 'when' statement becomes:
when(client.callApi(anyString(), eq(officeExpected))).thenReturn(responseOne);
This allows me to have better checking than "isA(Office.class)".
adding an answer for anyone with a more complex object.
answer from OP uses eq which works for simple objects.
However, I had a more complex object with many more fields. Its quite painful to create Mock object and fill in all the fields
public class CreateTenantRequest {
#NotBlank private String id;
#NotBlank private String a;
#NotBlank private String b;
...
...
}
I was able to use refEq to achieve the same thing without setting a value of each field.
Office officeExpected = new Office();
officeExpected.setId(22L);
verify(demoMock, Mockito.atLeastOnce()).foobarMethod(refEq(officeExpected, "a", "b"));
I write this getter/setter to list from Eclipse source menu:
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
And Sonar reporting two issues:
Return a copy of "date" & Store a copy of "date"
with the explanation
"Mutable members should not be stored or returned directly"
and a example code:
public String [] getStrings() {
return strings.clone();}
public void setStrings(String [] strings) {
this.strings = strings.clone();}
I think if my Date is null, it will throw a NullPointerException. Then I've changed my code to:
public Date getDate() {
if (this.date != null) {
return new Date(this.date.getTime());
} else {
return null;
}
}
public void setDate(Date date) {
if (date != null) {
this.date = new Date(date.getTime());
} else {
this.date = null;
}
}
And now marks other issue:
"Assigning an Object to null is a code smell. Consider refactoring".
I've searched in internet and set or return a new array is not a solution for me, I want to preserve my list to null if the setter param is null to overwrite an existing previous list.
I've the same problem for List, and I want to return/preserve null instead of a new ArrayList for an empty List. And in this case, the setter marks one more issue:
"Return an empty collection instead of null.".
What is the solution for this issue?
If you are in Java 8 and do not want to handle empty date, then maybe usage of Optional would help you.
Edit: Example of your "POJO" class
public class Toto {
public Optional<Date> myDate;
public Optional<Date> getMyDate() {
return this.myDate;
}
public void setMyDate(final Date myDate) {
this.myDate = Optional.ofNullable(myDate);
}
}
Example of code usage:
Toto toto = new Toto();
toto.setMyDate(null);
System.out.println("Value is null ? " + toto.getMyDate().isPresent());
System.out.println("Value: " + toto.getMyDate().orElse(new Date()));
Try to change the toto.setMyDate(...) with concrete date value to see what happen.
If you don't know what is Optional or how to use it, you can find plenty of examples.
BUT : This is only a way to solve your violation issue and i totally agree with Brad's remark, Optional are not intent to be used as a type, but more like a contract for potential empty / null returns.
In general, you should not correct your code in a bad way just to fix a violation, if the violation is not correct. And in your case i think you should just ignore the violation (as most of Sonar's one unfortunatly)
If you really want to use Java 8 and Optional in your code, then you POJO class would be like this (usage of Optional as a contrat on the getter only)
public class Toto {
public Date myDate;
public Optional<Date> getMyDate() {
return Optional.ofNullable(this.myDate);
}
public void setMyDate(final Date myDate) {
this.myDate = myDate;
}
}
This way,
You bean stay serializable (Optional is not)
You still enable your "client" code to have the choice on how to behave to empty / null value of your property
Configure your Sonar violation as a false positive as it is what you want instead of changing your code
Generally, while using static analysis tools to verify the code is valuable, you should not blindly fix every warnings which popups on you. You need to analyze the issue which is triggered and check if it really applies in your context.
Now to address the issues you are mentioning
Return a copy of "date" & Store a copy of "date"
This seems to be valid one. It is good practice to be defensive and not expose mutable state via getters/setters. So creating a defensive copy in getter/setter should be done. This can be done the way you did it, or by using new Java Time API, which provides immutable objects.
Assigning an Object to null is a code smell. Consider refactoring
IMO dubious one. The issue is raised by PMD plugin (which is the tool analyzing the code, SonarQube is displaying the report). Issue is raised by this rule http://pmd.sourceforge.net/pmd-4.3.0/rules/controversial.html#NullAssignment , as you can see it is in controversial category. I don't think there is anything wrong with your code, and proper action might be to ignore this warning and mark the issue as "won't fix". You can also configure your SonarQube to not use this particular rule in your Quality Profile setting.
Return an empty collection instead of null.
You did not provide the code which is triggering it, but this seems to be a valid piece of advice. It is generally better to return empty collections rather than nulls.
You don't have to explcitly set null in your setter, just use the value being passed in like this...
public void setDate(Date date) {
if (date != null) {
this.date = new Date(date.getTime());
} else {
this.date = date;
}
}
Personally I would never allow null values into my Value objects where ever possible, but that is just my opinionated coding style.
My advice to anyone is to prefer immutable value objects where you set all the values in the constructor and don't allow nulls in. This style may not be appropriate for all 3rd party libraries that expect the java bean getter/setters so be aware where it can be used effectively to simplify your code.
Edit
If the above code still gives you the warning and you must have the "property is not set yet" functionality, another approach is to define a "null object" like this
public static final Date NO_DATE = new Date(Long.MIN_VALUE);
public void setDate(Date date) {
this.date = (date == null) ? NO_DATE : new Date(date.getTime());
}
Users of this class can refer to the NO_DATE object like this, which still makes for readable code
if(toto.getDate() != NO_DATE) ...
Or encapsulate this into another method so it's used like this
if(toto.hasDate()) ...
Of course this doens't add much benefit over the Java 8 Optional approach from #kij but it does work with any version of Java
I don't know what are the best practices in my case :
1:
public class garage {
private List<Car> cars = new ArrayList<Cars>();
public String getCarSeatSomething(String carName, String brandName) {
for(Car car : cars){
if(car.getName().equals(carName)){
Seats seats = car.getSeats();
List<Brand> brands = seats.getBrands();
for(Brand brand: brands ){
if(brand.getName().equals(brandName)){
return brand.something();
}
}
}
}
return null;
}
...
}
I have many method like this, so I will have some redundant code with this solution.
Moreover, in my program, it's not "normal" that we don't find the car, so I think I have to use Exception no ?
2 :
public class Garage {
private List<Car> cars = new ArrayList<Car>();
public Something getCarSeatSomething(String carName, String brandName) {
Car car = searchCar(carName);
if(car == null)
return null;
else{
Seats seats = car.getSeats();
return seats.getSomething(brandName);
}
}
...
}
public class Seats {
private List<Brand> brands = new ArrayList<Brand>();
protected Something getSomething(brandName){
Brand brand = searchBrand(brandName);
if(brand == null)
return null;
else
return brand.something();
}
...
}
Less redundant code and less code for each method of the class Garage because the search are only in searchBrand and searchCar.
But I have allways the problem of exceptions.
So, my last solution, is to throw exception in the searchBrand and searchCar methods, add throws at all the methods (like getCarSeatSomething) which use searchBrand/searchCar and try ... catch when I use these methods (like getCarSeatSomething).
Is that correct ?
If not, have you got better ideas ?
It looks like car name and brand name will be user provided input. In that case, you should expect users to provide names that do not exist. It is not exceptional. Return null and in the top layer, return an error message to the user. It seems reasonable that you might try to "get" something and not get it at all. null is appropriate here. But make sure you are consistent about this behavior across your application and you document it.
If an entity must contain a particular attribute then getter methods for that attribute should throw an exception if the entity cannot provide the attribute.
If it is optional for an entity to contain the attribute, then getter methods should not throw an exception.
Some scenarios will involve both cases, where in some contexts access to the attribute is mandatory and in other contexts it is optional. Then you should provide two "getter" methods, one that will throw an exception if the attribute cannot be returned, and the other an Optional value. I recommend using the method naming convention of getEntity for mandatory getter methods and findEntity for optional getter methods.
In the case where an entity must contain a particular attribute and the getter method cannot complete the request, you have a malformed entity. If your entity is throwing exceptions because it cannot return mandatory attributes you have a bug or problems with how you created the entity.
Entities should never be created without mandatory attributes. Constructors and factories should enforce mandatory attributes. For entities that must be created and not fully formed (like Data Access Objects) separate validation should be applied to the entities before being used. Or separate your domain entity and DAO into separate but equivalent types.
To describe the situation: you have a elaborate data hierarchy, with possibly a chained access:
x.getLiat().get(3).getAs().lookupB("a1").getC();
This may lead to a design with either expectable NullPointerExceptions to be handled (ugly) or Excptions.
Java 8 proposes Optional<T> to explicitly handle in one expression what otherwise could be a null.
x.getA().orElse(a).getB().orElseThrow(() -> new XException()).getC();
Better yet is to use java 8's streams, with filtering, mapping, find any/first capabilities.
private List<Car> cars = new ArrayList<>();
public Optional<String> getCarSeatSomething(String carName, String brandName) {
return cars.stream()
.filter((car) -> car.getName().equals(carName))
.flatMap{(car) -> car.getSeats())
.flatMap((seats) -> seats.getBrands())
.filter((brand) -> brand.getName().equals(brandName))
.findFirst();
}
I would like to describe a nasty issue that occurs when making naive use of Java enums in the context of JPA entities. Let's take a look at how this problem can occur.
First the domain model:
Say I have an Text JPA entity that represents piece of text (novel, news article, etc.). Here is the JPA entity:
#Entity
public class Text {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
#Version
#Column(name = "version")
private Integer version;
private String content;
#Enumerated
#ElementCollection
private Set<Style> styles;
//Setters and getters omitted.
To an instance of Text, one or many styles can be applied such as italic, bold and so on. The style is represented as a java enum.
To start with, we assume that the application starts its life with the following enum:
public enum Style {
BOLD, ITALIC
}
The test below will then insert the following lines in a relational database:
Integration test:
#Test
#Rollback(value=false)
public void inEarlyLifePersist() {
Text text =new Text();
text.setContent("This is my beautiful novel...");
text.setStyles(EnumSet.of(Style.BOLD, Style.ITALIC));
text.persist();
}
Data in text table:
# id, content, version
11, This is my beautiful novel..., 0
*Data in text_style table:*
# text, styles
11, 0
11, 1
Then, later on, some ill-advised developer decides to add a new style: STRIKE_THROUGH to our Style enum placing this new enum constant/value as the first one:
public enum Style {
STRIKE_THROUGH, BOLD, ITALIC
}
and then a new record is inserted in DB as follows:
#Test
#Rollback(value=false)
public void afterChangeToEnumPersist() {
Text text =new Text();
text.setContent("This is my beautiful short story...");
text.setStyles(EnumSet.of(Style.STRIKE_THROUGH, Style.BOLD));
text.persist();
}
In text table:
# id, content, version
14, This is my beautiful short story..., 0
And *in text_style table:*
# text, styles
14, 0
14, 1
Obviously, the domain model is seriously compromised now!
My question is what are the possible strategies to avoid spelling disaster in the domain as is the case above (other than the obvious solution to place the STRIKE_THROUGH enum constant after ITALIC)?
edit 1: Obviously I do not want to store strings (see EnumType.STRING) in my database for obvious performance reasons i.e. data retrieval and storage performance would be seriously affected!
You need to redefine your enum like below.
public enum Style {
STRIKE_THROUGH(2), BOLD(0), ITALIC(1)
Style(int code){
this.code=code;
}
}
And implement a Hibernate User type to persist the code.
There's an option (EnumType.STRING) to use the actual name of the enum value (the String returned by { name() } instead of the ordinal. That way you can reorganize your enum values, but then you are tied to the names of the enum values.
The ideal solution would be to be able to declaratively tell the JPA implementation to use an arbitrary property of the enum as the database identifier. But AFAIK, that it's not provided in the current JPA specs, it would be great to have such a feature in future JPA specs.
The answer by Sajan shows how to implement that using a Hibernate-specific feature.
The Enumerated annotation also knows a property that specifies the EnumType. Two types exist: EnumType.ORDINAL and EnumType.STRING. ORDINAL is the default one.
So, if you do it the following way
#Enumerated(EnumType.STRING)
you will see the enumeration names in the DB column (and not the ordinals). Of course, you are now vulnerable to name changes in your enumeration. You have to die one death, but I think, the names are better.
I can't see why people find the enum names more reliable than their ordinals. Actually, there are many good reasons for renaming enums (fixing typos, changed names due to politics or political correctness, etc.), but I can't see any good reason for reordering them.
Both renaming and reordering happens and the only thing which can help is a test. Unfortunately, the best test I can think of will fail on any change. Fortunately, the test can tell what happened and then be fixed easily.
public void testE1IsStable() {
assertEnumUnchanged(E1.class, 4, "bec419c8380dbe9ec3b86a7023a55107");
}
public void testE2IsStable() {
assertEnumUnchanged(E2.class, 3, "1e89e93c6cbdbb7311b814c19d682548");
}
private void assertEnumUnchanged(Class<? extends Enum<?>> enumClass, int expectedCount, String expectedHash) {
final Object[] enumConstants = enumClass.getEnumConstants();
if (expectedCount < enumConstants.length) {
final Object[] shortened = Arrays.copyOf(enumConstants, expectedCount);
assertEquals("Enum constants may be only appended! Ask balteo!",
expectedHash, hashAsString(shortened));
fail("An enum constant has been added! This test needs to be updated. Ask balteo!");
} else if (expectedCount > enumConstants.length) {
fail("Enum constants must not be removed! Ask balteo!");
} else {
assertEquals("Enum constants must not be reordered! If they get renamed, this test must be updated. Ask balteo!",
expectedHash, hashAsString(enumConstants));
}
}
private String hashAsString(Object[] enumConstants) {
final Hasher hasher = Hashing.md5().newHasher();
for (final Object o : enumConstants) hasher.putUnencodedChars(o.toString());
return hasher.hash().toString();
}
I write a little web API which should it make easy to create URIs. Each resource class should contain a method createURI which takes the needed parameters. This method should use a helper method, populateUriTemplate, in the background to create an URI string. populateUriTemplate needs key value pairs to populate an URI template. In another language like Scala or Python I would use named parameters, but Java doesn't support them. So the question is: How to simulate named parameters in Java?
The straight forward solution would be to create a map:
public String createUri(int id, String name){
Map<String, Object> params = new HashMap<String, Object>();
params.put("id", id);
params.put("name", name);
return populateUriTemplate(params);
}
But I don't like to create a map first and put each parameter to it.
Another idea is to use a static method, param, to create key value pairs:
public String createUri(int id, String name){
return populateUriTemplate(param("id", id), param("name", name));
}
Looks much better to me!
It could be refined a bit to make it more self-explanatory, even if a few more characters are needed:
public String createUri(int id, String name){
return populateUriTemplate(key("id").value(id), key("name").value(name));
}
I've also thought of the builder pattern, but this would force the user of my API to create an explicit builder for each resource class, what would be tedious without a benefit. The type of the parameter is not important, as long as a proper implemented toString method exists.
My favourite is one of the both approaches with the static methods above (param(key, value) or key(k).value(v)). Do you know a better way to simulate named parameters in this case?
For some ideas on the builder pattern, you could see this blog post by Stephan Schmidt.
You also just gave me the idea to do the following, with fluent interfaces, a Callable, and a static method:
createUri().id(5).name("dennetik").call();
Which would require createing a Callable class (CreateUri) with the static method:
public static final CreateUriFluentInterface createUri() {
return FluentInterface.of(new CreateUri(), CreateUriFluentInterface.class);
}
And a fluent interface, like this:
public interface CreateUriFluentInterface {
public CreateUriFluentInterface id(Integer id);
public CreateUriFluentInterface name(String name);
}
Which isn't that much boilerplate code, is it?
(Well, if you tone down that horribly named CreateUriFluentInterface a bit, it isn't.)
(You would probably have CreateUriFluentInterface extend Callable<String>, to be able to reroute the call to Callable#call())
populateUriTemplate("id",id, "name",name);
void populateUriTemplate(Object... nvs){
for(int i=0; i<nvs.length/2; i++)
....
}
Maybe you like this approach:
class Params {
private HashMap<String, Object> allParams = new HashMap<String,Object>();
public Params(ParamEntry...params) {
for( ParamEntry p : params ) {
allParams.put(p.name, p.value);
}
}
public getParam(String name) {
return allParams.get(name);
}
class ParamEntry {
public String name;
public Object value;
}
}
public String createUri(Params.ParamsEntry ... params){
return populateUriTemplate(new Params(params));
}
To call it use
createUri(new Param.ParamEntry("name", valueObject) );
Inside the populateUriTemplate...
just use params.get("name");
Spring MVC does exactly this. As well as being able to bind requests to specific methods in controller classes, you can bind request parameters to method parameters. You can have a look to see how it works, but basically it picks a strategy to map the right request parameter to the right method parameter.
You basically get something like:
public String createUri(#RequestParam int id, #RequestParam String name){
return populateUriTemplate(id, name);
}
This is almost silly and slightly off topic, but using Lombok's #Builder annotation takes this closer to the desired result.
Furthermore if the builder, builder method and build method names are changed to _ they almost disappear:
import static foo.Template._;
class Resource {
String createURI(String id, String name) {
return populateURITemplate(_.id(id).name(name)._());
}
String populateURITemplate(Template t ){
return t.id+"="+t.name;
}
}
#Builder(builderClassName = "_", builderMethodName = "_", buildMethodName = "_" )
class Template {
static _ _ = _();
String id;
String name;
}
Named parameters are not the way:
Named parameters do not make your code any cleaner in this case. I would argue that they make things more complex and error prone in Java because you lose type safety and you lose compiler warnings about identifiers that do not exist.
TypeSafe Immutable Fluent Builders:
I wrote an article on a UrlBuilder implementation earlier this year, it shows a type safe fluent interface that enforces order of construction for mandatory input and allows for optional parts with sane defaults as well.
Now I will be the first to admit that the approach I use is fairly verbose, but it is extremely productive once that initial price is paid. It works with dependency injection and is easily unit testable and most importantly is composable for specialization.
final URL url1 = new UrlBuilder().scheme("http").host("www.google.com").build();
System.out.println("url1 = " + url1);
final URL url2 = new UrlBuilder().scheme("https").userInfo("xkcd", "correcthorsebatterystaple").host("admin.xkcd.com").build();
System.out.println("url2 = " + url2);
Produces:
url1 = http://www.google.com
url2 = https://xkcd:correcthorsebatterystaple#admin.xkcd.com
I am addressing the verbosity of the anonymous inner class implementations of the interfaces with another approach I am experimenting with; type safe implementations of value objects from interfaces using dynamic proxies.
This will do away with the boilerplate value objects and replace them with Map<String,?> but put a dynamically generated type safe immutable Interface wrapper around them.
I encourage you to read about both of these and see how combining them gives you a better solution than named properties ever would.
When I get time to refactor my UrlBuilder with the dynamic proxies I will post another blog post about it as well.
Named Parameters via Guice
If you are dead set on named parameters then I would recommend looking at Guice #Named bindings. You still lose the compile type checks and safety but at least you get some validations from Guice.
public class RealBillingService implements BillingService {
#Inject
public RealBillingService(#Named("Checkout") CreditCardProcessor processor,
TransactionLog transactionLog) {
...
}