简体   繁体   中英

Property or field 'name' cannot be found on object of type 'java.util.Optional' - maybe not public or not valid?

I want to show Room Detail when I click name of room.. But I have a problem I don't know why. I using Spring MVC,Spring Boot,Spring Data and Thymeleaf

org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'name' cannot be found on object of type 'java.util.Optional' - maybe not public or not valid?

I think the problem is about Optional in Service when I use Spring Data findById() This is my code

Room Model

@Entity
@Table(name ="room")
public class Room implements Serializable {
 private static final long serialVersionUID = 1L;
 @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "ID_room", nullable = false)
    private String id;


    @Column(name = "name_room", nullable = false)
    private String name;


    @Column(name = "Description")
    private String describe;

    @Column(name = "ID_status")
    private String status;

    @Column(name = "room_image")
    private String image;

    public Room() {
        super();
    }

    public Room(String id, String name, String describe, String status,String image) {
        super();
        this.id = id;
        this.name = name;
        this.describe = describe;
        this.status = status;
        this.image = image;

    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescribe() {
        return describe;
    }

    public void setDescribe(String describe) {
        this.describe = describe;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getImage() {
        return image;
    }

    public void setImage(String image) {
        this.image = image;
    }


}

Room Service

public interface RoomService {


Optional<Room> findOne(String id);


}

Room Service Implement

public class RoomServiceImpl implements RoomService {
@Autowired
private RoomRepository roomRepository;

@Override
public Optional<Room> findOne(String id) {

    return roomRepository.findById(id);
}

}

RomController

@GetMapping("/room/{id}/detail")
public String detail(@PathVariable String id, Model model) {
    model.addAttribute("room", romService.findOne(id));
    return "roomDetail";
}

roomDetail.html

<div class="col-md-7 single-top-in">
                    <div class="single-para">
                        <h4><tr th:text="${room.name}"></h4>
                        <div class="para-grid">
                            <span  class="add-to">$32.8</span>
                            <a href="#" class="hvr-shutter-in-vertical cart-to">Add to Cart</a>                 
                            <div class="clearfix"></div>
                         </div>
                        <h5>100 items in stock</h5>

                        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p>

org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'name' cannot be found on object of type 'java.util.Optional' - maybe not public or not valid?

means that Spring didn't manage to interpolate the name property used in your template :

  <h4><tr th:text="${room.name}"></h4>

It is expected because you passed the Optional<Room> object to the MVC model instead of passing the Room object.
You have to unwrap the object contained in the Optional before adding it to the model.
For example :

romService.findOne(id).ifPresent(o -> model.addAttribute("room", o));

an example:

 if( user.isPresent() ) {
            model.addAttribute("user", user.get());

or

Long userId = ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getId();
        Optional<User> user = userService.findById(userId);

        if( user.isPresent() ) {
            model.addAttribute("user", user.get());
}

There's one thing I would mention, which is the native convention expected by thymeleaf for nested fields/properties

private FieldType fieldname;
public FieldType getFieldname(){return this.fieldname;}
public void setFieldname(FieldType ff){this.fieldname=ff;}

Note how field names are small case but getFieldname has the starting 'f' in caps. Similarly for the setters.

If you class has getfieldname() and not getFieldname(), you might have trouble

In my case csv used \\t instead of comma created error. Replacing or use \\t separator solved issue.

Always check for the entity's getters and setters methods. In my case I had getpatientId instead of getPatient . Since spring does theses things automatically, it expects these conventions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM