Java / Jackson - «нераспознанный токен», передающий параметр объекта JSON - PullRequest
0 голосов
/ 30 октября 2018

Веб-сервис Java JAX-RS с Джерси / Джексоном, метод сервиса ожидает параметр пользователя (POJO) как JSON. Клиентское приложение (Angular 6) отправляет запрос POST, содержащий параметр User (сериализованный как JSON). Сбой вызова метода службы с сообщением об ошибке: «Нераспознанный токен« jsonUser »: ожидалось (« истина »,« ложь »или« ноль »)».

Вот класс User (POJO) - вы можете заметить, что я пытался аннотировать все свойства с помощью @JsonProperty, но это не нужно, поскольку я не переименовываю их:

import java.io.Serializable;

import javax.ws.rs.FormParam;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;

//import org.glassfish.jersey.media.multipart.FormDataParam;

/**
 * JavaBean for passing the User properties between the UI app (Angular) 
 * and TearsWs. Implementation requires this to be serializable (JSON).
 */
@JsonIgnoreProperties({ "DELIM" })
public class User implements Serializable {
    private String userName;
    private String employeeId;
    private String employeeName;
    private String homeUnitCode;
    private boolean certifier;
    private HomeUnit[] tkHomeUnits;
    private boolean supervisor;
    private Employee[] whoISupervise;
    private boolean hrStaff;
    private boolean collector;

    private final static String DELIM = ", ";

    public User() {
    }

    // getters / setters
    //@JsonProperty("userName")
    public void setUserName(String ldapUid) {
        this.userName = ldapUid;
    }
    public String getUserName() {
        return this.userName;
    }

    //@JsonProperty("employeeId")
    public void setEmployeeId(String employeeId) {
        this.employeeId = employeeId;
    }
    public String getEmployeeId() {
        return this.employeeId;
    }

    //@JsonProperty("employeeName")
    public void setEmployeeName(String employeeName) {
        this.employeeName = employeeName;
    }
    public String getEmployeeName() {
        return this.employeeName;
    }

    //@JsonProperty("homeUnitCode")
    public void setHomeUnitCode(String homeUnitCode) {
        this.homeUnitCode = homeUnitCode;
    }
    public String getHomeUnitCode() {
        return this.homeUnitCode;
    }

    //@JsonProperty("certifier")
    public void setCertifier(boolean certifier) {
        this.certifier = certifier;
    }
    public boolean getCertifier() {
        return this.certifier;
    }

    //@JsonProperty("tkHomeUnits")
    public void setTkHomeUnits(HomeUnit[] tkHomeUnitCodes) {
        this.tkHomeUnits = tkHomeUnitCodes;
    }
    public HomeUnit[] getTkHomeUnits() {
        return this.tkHomeUnits;
    }

    //@JsonProperty("supervisor")
    public void setSupervisor(boolean supervisor) {
        this.supervisor = supervisor;
    }
    public boolean isSupervisor() {
        return this.supervisor;
    }

    //@JsonProperty("whoISupervise")
    public void setWhoISupervise(Employee[] whoISupervise) {
        this.whoISupervise = whoISupervise;
    }
    public Employee[] getWhoISupervise() {
        return this.whoISupervise;
    }

    //@JsonProperty("hrStaff")
    public void setHrStaff(boolean hrStaff) {
        this.hrStaff = hrStaff;
    }
    public boolean isHrStaff() {
        return this.hrStaff;
    }

    //@JsonProperty("collector")
    public void setCollector(boolean collector) {
        this.collector = collector;
    }
    public boolean isCollector() {
        return this.collector;
    }

    //methods
    public boolean hasTauthority() {
        return this.certifier || this.collector;
    }

    public String toString() {
        int tkHUs = (tkHomeUnits == null) ? 0 : tkHomeUnits.length;
        return "[User: "
            + "userName=" + this.userName + DELIM 
            + "employeeId=" + this.employeeId + DELIM 
            + "employeeName=" + this.employeeName + DELIM 
            + "homeUnitCode=" + this.homeUnitCode + DELIM
            + "certifier=" + this.certifier + DELIM 
            + "hrStaff=" + this.hrStaff + DELIM 
            + "collector=" + this.collector + DELIM
            + "I can certify " + tkHUs + " homeUnits" + "]";
    }
}

Вот метод службы (Java), который должен принимать и обрабатывать запрос POST:

/**
 * Web service method.
 */
@POST
@Path("getTkHomeUnitEmployees")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response getTkHomeUnitEmployees(User user, @HeaderParam("X-Request-Param") String homeUnitCode) throws Exception {
    String exceptionMessage;

    if (user == null) {
        exceptionMessage = "getTkHomeUnitEmployees() received a null User.";
        log.error(exceptionMessage);
        Response response = Response
                .status(500)
                .entity(exceptionMessage)
                .build();
        return response;
    }
    if (homeUnitCode == null || homeUnitCode.equals("")) {
        exceptionMessage = "getTkHomeUnitEmployees() received a null HomeUnitCode.";
        log.error(exceptionMessage);
        Response response = Response
                .status(500)
                .entity(exceptionMessage)
                .build();
        return response;
    }
    if (!user.hasTauthority()) {
        exceptionMessage = "getTkHomeUnitEmployees() received a request from a non-timekeeper and non-collector.";

        log.error(exceptionMessage);
        Response response = Response
                .status(500)
                .entity(exceptionMessage)
                .build();
        return response;
    }
    try {
        Employee[] tkHomeUnitEmployees = new SecurityDao().getTkHomeUnitEmployees(user.getEmployeeId(), homeUnitCode);

        Response response = Response
                .ok(tkHomeUnitEmployees)
                .header("Access-Control-Allow-Origin", "*")
                .build();
        return response;
    } catch (Exception ex) {
        exceptionMessage = "getTkHomeUnitEmployees(): " + ex;
        Response response = Response
                .status(500)
                .entity(exceptionMessage)
                .build();
        return response;
    }
}

Объект User (сторона клиента, Javascript) преобразуется в JSON и инкапсулируется как параметр в HttpParams; POST передает его в теле запроса.

Вот (угловой) клиентский метод, который отправляет POST-запрос веб-службе:

getTkHomeUnitEmployees(user: User, homeUnitCode: string): Observable<Employee[]> {
    const headers = new HttpHeaders()
        .set('Content-Type', 'application/json')
        .set('X-Request-Param', homeUnitCode); // homeUnitCode parameter in HttpHeaders

    const httpOptions = {
        headers: headers
    };

    let jsonUser: string = JSON.stringify(user);

    const httpParams = new HttpParams()
        .set('jsonUser', jsonUser);

    let postUrl = this.wsUrl + 'getTkHomeUnitEmployees';
    //postUrl += '?homeUnitCode=' + homeUnitCode; // homeUnitCode parameter as QueryParam

    let obsArrayEmployees: Observable<Employee[]> = this.httpClient.post<Employee[]>(postUrl, httpParams, httpOptions);
    return obsArrayEmployees;
}

... здесь я отлаживаю клиента (@ Tools Dev Tools) с перерывом в методе getTkHomeUnitEmployees ():

debug getTkHomeUnitEmployees

... Я отобразил значение jsonUser в консоли:

debug - jsonUser value

... вот ошибка в Ответе:

error - Response 400

error - Response Unrecognized token

... а вот и параметры запроса.

error - Request payload

Итак, похоже, что JsonParser Джексона пытается прочитать и проанализировать параметр, отправленный в запросе, но этот параметр включает в себя «jsonUser =» в начале как часть его значения (для анализа json). Это явно неправильно ...

Сервисный метод взрывается до фактического ввода / обработки кода; Я не могу установить точку останова в методе службы, чтобы проверить значение параметра. Он ведет себя как ответ «неверный параметр, возврат к вызывающей стороне».

Я думал вручную взломать "jsonUser =" из него (на стороне клиента), но его там нет. На клиенте «jsonUser =» не является частью значения параметра; Я полагаю, что это просто синтаксис ключ = значение параметра http (имя-параметра = значение-параметра), возможно, он добавляется, когда параметр инкапсулируется в объект HttpParams.

Очевидно, что я делаю что-то не так, но я не смог понять это; Я думал, что это был правильный способ сделать это, но, видимо, нет. Надеюсь, кто-нибудь может помочь в ближайшее время, я застрял на этом уже пару дней.

1 Ответ

0 голосов
/ 02 ноября 2018

Вам не нужно преобразовывать объект 'user' в строку для передачи в бэкэнд. Попробуйте передать объект пользователя как есть.

this.httpClient.post<Employee[]>(postUrl, user, httpOptions);

А также, пожалуйста, проверьте, действительно ли переданные параметры соответствуют оставшейся службе остальных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...