Lỗi xác thực: Giá trị không hợp lệ


80

Tôi gặp sự cố với ap: selectOneMenu, bất kể tôi làm gì, tôi không thể yêu cầu JSF gọi bộ định trên thực thể JPA. Xác thực JSF không thành công với thông báo này:

form: location: Validation Error: Giá trị không hợp lệ

Tôi có cái này hoạt động trên một số lớp khác cùng loại (tức là tham gia các lớp bảng) nhưng không thể cho cuộc đời tôi làm cho cái này hoạt động.

Nếu ai đó có thể đưa ra một số mẹo khắc phục sự cố / gỡ lỗi cho loại vấn đề này thì sẽ được đánh giá rất cao.

Sử dụng báo cáo nhật ký, tôi đã xác minh những điều sau:

  1. Trả Convetervề nullgiá trị chính xác, không phải .
  2. Tôi không có Xác thực Bean trong các thực thể JPA của mình.
  3. Người thiết lập setLocation(Location location)không bao giờ được gọi.

Đây là ví dụ đơn giản nhất tôi có thể làm và nó chỉ đơn giản là sẽ không hoạt động:

<h:body>
    <h:form id="form">
        <p:messages id="messages" autoUpdate="true" />
        <p:selectOneMenu id="location" value="#{locationStockList.selected.location}" converter="locationConverter">
            <p:ajax event="change" update=":form:lblLocation"/>
            <f:selectItems value="#{locationStockList.locationSelection}"/>
        </p:selectOneMenu>
    </h:form>
</h:body>

Người chuyển đổi:

@FacesConverter(forClass=Location.class, value="locationConverter")
public class LocationConverter implements Converter, Serializable {
    private static final Logger logger = Logger.getLogger(LocationConverter.class.getName());

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        if (value.isEmpty())
            return null;
        try {
            Long id = Long.parseLong(value);
            Location location = ((LocationManagedBean) context.getApplication().getELResolver().getValue(context.getELContext(), null, "location")).find(id);
            logger.log(Level.SEVERE, "Converted {0} to {1}" , new Object[] {value, location});
            return location;
        } catch (NumberFormatException e) {
            return new Location();
        }
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        if (value == null || value.toString().isEmpty() || !(value instanceof Location))
            return "";
        return String.valueOf(((Location) value).getId());
    }    
}

Đầu ra bảng điều khiển:

// Getter method
INFO: Current value=ejb.locations.Location[id=null, name=null, latitude=0.0, longitude=0.0] 
// Session Bean
INFO: Finding ejb.locations.Location with id=3 
// Session Bean
INFO: ### Returning : ejb.locations.Location[id=3, name=mdmd, latitude=4.5, longitude=2.3] 
// Converter
SEVERE: Converted 3 to ejb.locations.Location[id=3, name=mdmd, latitude=4.5, longitude=2.3] 
// Getter method -> Where did my selected Location go ??
INFO: Current value=ejb.locations.Location[id=null, name=null, latitude=0.0, longitude=0.0] 

Câu trả lời:


143

Xác thực không thành công với thông báo "biểu mẫu: vị trí: Lỗi xác thực: Giá trị không hợp lệ"

Lỗi này dẫn đến việc mục đã chọn không khớp với bất kỳ giá trị mục đã chọn nào có sẵn được chỉ định bởi bất kỳ <f:selectItem(s)> thẻ lồng nhau nào trong quá trình xử lý yêu cầu gửi biểu mẫu.

Là một phần của biện pháp bảo vệ chống lại các yêu cầu giả mạo / bị tấn công, JSF sẽ nhắc lại tất cả các giá trị mặt hàng đã chọn hiện có và kiểm tra xem có selectedItem.equals(availableItem) trả về truecho ít nhất một giá trị mặt hàng có sẵn hay không. Nếu không có một giá trị mục nào khớp, thì bạn sẽ gặp chính xác lỗi xác thực này.

Quá trình này về cơ bản được trình bày như bên dưới, theo đó bean.getAvailableItems()đại diện hư cấu toàn bộ danh sách các mục được chọn có sẵn như được xác định bởi <f:selectItem(s)>:

String submittedValue = request.getParameter(component.getClientId());
Converter converter = component.getConverter();
Object selectedItem = (converter != null) ? converter.getAsObject(context, component, submittedValue) : submittedValue;

boolean valid = false;

for (Object availableItem : bean.getAvailableItems()) {
    if (selectedItem.equals(availableItem)) {
        valid = true;
        break;
    }
}

if (!valid) {
    throw new ValidatorException("Validation Error: Value is not valid");
}

Vì vậy, dựa trên logic ở trên, vấn đề này về mặt logic có thể có ít nhất các nguyên nhân sau:

  1. Mục đã chọn bị thiếu trong danh sách các mục có sẵn.
  2. Các equals()phương pháp của lớp đại diện cho các sản phẩm được chọn là mất tích hoặc bị hỏng.
  3. Nếu một tập quán Convertercó liên quan, thì nó đã trả lại sai đối tượng trong getAsObject(). Có lẽ nó thậm chí null.

Để giải quyết nó:

  1. Đảm bảo rằng chính xác cùng một danh sách được giữ nguyên trong lần yêu cầu tiếp theo, đặc biệt là trong trường hợp có nhiều menu xếp tầng. Làm cho hạt đậu @ViewScopedthay vì @RequestScopedsẽ sửa chữa nó trong hầu hết các trường hợp. Đồng thời đảm bảo rằng bạn không thực hiện logic nghiệp vụ trong phương thức getter của <f:selectItem(s)>, mà thay vào đó trong @PostConstructphương thức sự kiện hành động (người nghe). Nếu bạn đang dựa trên các thông số yêu cầu cụ thể, sau đó bạn cần phải lưu trữ một cách rõ ràng chúng trong @ViewScopedđậu, hoặc để lại vượt qua chúng trên yêu cầu tiếp theo của ví dụ <f:param>. Xem thêm Cách chọn phạm vi đậu phù hợp?
  2. Đảm bảo rằng equals()phương pháp được thực hiện đúng. Điều này đã được thực hiện ngay trên các loại Java chuẩn như java.lang.String, java.lang.Number, vv, nhưng không nhất thiết phải trên các đối tượng tùy chỉnh / đậu / entites. Xem thêm Cách đúng để thực hiện hợp đồng bình đẳng . Trong trường hợp bạn đã sử dụng String, hãy đảm bảo rằng mã hóa ký tự yêu cầu được định cấu hình đúng. Nếu nó chứa các ký tự đặc biệt và JSF được định cấu hình để hiển thị đầu ra dưới dạng UTF-8 nhưng diễn giải đầu vào như ISO-8859-1, thì nó sẽ không thành công. Xem thêm đầu vào Unicode được truy xuất qua PrimeFaces, các thành phần đầu vào bị hỏng .
  3. Gỡ lỗi / ghi nhật ký các hành động tùy chỉnh của bạn Convertervà sửa nó cho phù hợp. Để biết hướng dẫn, hãy xem thêm giá trị cài đặt Lỗi chuyển đổi cho 'null Converter' Trong trường hợp bạn đang sử dụng java.util.Datecác mục có sẵn với <f:convertDateTime>, hãy đảm bảo rằng bạn không quên phần toàn thời gian trong mẫu. Xem thêm lỗi "Lỗi xác thực: Giá trị không hợp lệ" từ f: datetimeConverter .

Xem thêm:


Nếu ai đó có thể đưa ra một số mẹo khắc phục sự cố / gỡ lỗi cho loại vấn đề này thì sẽ được đánh giá rất cao.

Chỉ cần hỏi một câu hỏi rõ ràng và cụ thể ở đây. Đừng hỏi những câu hỏi quá rộng;)


@BalusC: Chính xác thì nó nằm ở đâu trong mã mojarra để equalskiểm tra này xảy ra. Tình hình của tôi hơi phức tạp. Tôi tạo thành phần tùy chỉnh của riêng mình cho phép người dùng có bố cục radio phức tạp. Nó hoạt động tốt nếu tôi chỉ có một nhóm radio (f: selectItems ngay bên dưới thành phần tùy chỉnh của tôi). Tuy nhiên khi bố cục trở nên phức tạp hơn (nhiều nhóm radio, mỗi nhóm có f: selectItems riêng nhưng tất cả đều chia sẻ cùng một lựa chọn), tôi phải có f: selectItems bên trong ui: repeat, thì ui: repeat nằm trong thành phần tùy chỉnh của tôi. Sau đó tôi gặp phải vấn đề này. Tôi muốn xem mã mojarra xử lý việc này
Thang Pham

Ngoài ra, f: selectItems của tôi là kiểu Chuỗi, vì vậy tôi chắc chắn đây không phải là vấn đề chuyển đổi, tôi nghĩ nguyên nhân là do danh sách f: selectItems không có ở đó trong giai đoạn xác thực.
Thang Pham

Bạn có thể nói rõ hơn về cách sử dụng f: param để gửi trạng thái cho bean quản lý để nó có thể tạo lại "trạng thái ban đầu" không ??? Cảm ơn.
Agustí Sánchez

1
Gặp lỗi tương tự. Tôi đang sử dụng SelectItemsConverter và thành phần này nằm bên trong một tập trường bị vô hiệu hóa - vì vậy nó cũng bị vô hiệu hóa. Đó có phải là một hành vi đã biết không?
Gilberto

Nếu bạn đang sử dụng enum cho các mục để hiển thị và đậu hỗ trợ của bạn có kiểu Chuỗi để đặt giá trị trong bean và không sử dụng bất kỳ trình chuyển đổi nào, bạn sẽ gặp lỗi tương tự. Đó là cách tôi kết thúc ở đây.
Philip Puthenvila

2

Trong trường hợp của tôi, tôi đã quên triển khai các phương thức get / set đúng. Nó xảy ra bởi vì tôi đã thay đổi rất nhiều thuộc tính trong quá trình phát triển.

Nếu không có phương thức nhận phù hợp, JSF không thể khôi phục mục đã chọn của bạn và xảy ra những gì BalusC đã nói ở mục 1 trong câu trả lời của anh ấy:

1. Mục đã chọn bị thiếu trong danh sách các mục có sẵn. Điều này có thể xảy ra nếu danh sách các mục có sẵn được phục vụ bởi một bean phạm vi yêu cầu không được khởi động lại đúng cách theo yêu cầu tiếp theo hoặc thực hiện sai công việc kinh doanh bên trong phương thức getter khiến nó trả về một danh sách khác theo một cách nào đó.


1

Đây có thể là vấn đề về bộ chuyển đổi hoặc vấn đề DTO khác. Cố gắng giải quyết vấn đề này, bằng cách thêm các phương thức hashCode () và equals () trong đối tượng DTO của bạn; Trong trường hợp trên, bạn có thể tạo các phương thức này trong lớp đối tượng Location được chỉ ra là 'DTO' ở đây.

Thí dụ:

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + (int) (id ^ (id >>> 32));
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Location other = (Location) obj;
    if (id != other.id)
        return false;
    return true;
}
  • Xin lưu ý rằng ví dụ trên dành cho 'id' thuộc loại 'dài'.

Giống như đã nêu ở # 2 trong câu trả lời được chấp nhận và bỏ phiếu tán cao
Kukeltje
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.