21

I am using Java 15 preview feature record in my code, and defined the record as follow

public record ProductViewModel
        (
                String id,
                String name,
                String description,
                float price
        ) {
}

In the controller level I have the below code

@Put(uri = "/{id}")
public Maybe<HttpResponse> Update(ProductViewModel model, String id) {
        LOG.info(String.format("Controller --> Updating the specified product"));
        return iProductManager.Update(id, model).flatMap(item -> {
            if(item == null)
                return Maybe.just(HttpResponse.notFound());
            else
                return Maybe.just(HttpResponse.accepted());
        });
    }

From the UI in the model the value of id is not passed, however, it is passed as a route parameter. Now I want to set the value in the controller level, something like

model.setid(id) // Old style

How can I set the value to the record particular property

Naman
  • 27,789
  • 26
  • 218
  • 353
San Jaisy
  • 15,327
  • 34
  • 171
  • 290

3 Answers3

40

You can't. Record properties are immutable. What you can do however is add a wither to create a new record with same properties but a new id:

public record ProductViewModel(String id,
                               String name, 
                               String description,
                               float price) {

    public ProductViewModel withId(String id) {
        return new ProductViewModel(id, name(), description(), price());
    }
} 
daniel
  • 2,665
  • 1
  • 8
  • 18
7

If you need to mutate an attribute, then you need to use a class instead of a record.

From the JEP:

Enhance the Java programming language with records, which are classes that act as transparent carriers for immutable data. Records can be thought of as nominal tuples.

So, you'd better use a class if you need that behavior.

fps
  • 33,623
  • 8
  • 55
  • 110
  • 1
    I'd also add that you explicitly named your class as a 'model' which generally implies it is mutable. – stridecolossus Dec 11 '20 at 15:29
  • 2
    @stridecolossus No, it doesn't, not _generally._ In fact in domain driven design large parts of the domain model will be value objects that by definition do not have a behaviour and thus should be immutable (it is derived from the fact that for values there is no concept of identity other than the value itself). – Amadán Nov 18 '22 at 07:14
6

You cannot modify them. From the Oracle page:

A record class is a shallowly immutable, transparent carrier for a fixed set of values, called the record components. The Java language provides concise syntax for declaring record classes, whereby the record components are declared in the record header. The list of record components declared in the record header form the record descriptor.

From the Java Language Specification Section 8.10 one can read the following:

A record declaration is implicitly final. It is permitted for the declaration of a record class to redundantly specify the final

and

8.10.3 Record Members

A record class has for each record component appearing in the record component list an implicitly declared field with the same name as the record component and the same type as the declared type of the record component. This field is declared private and final. The field is annotated with the annotations, if any, that appear on the corresponding record component and whose annotation types are applicable in the field declaration context, or in type contexts, or both.

dreamcrash
  • 47,137
  • 25
  • 94
  • 117