簡體   English   中英

為什么我的二傳手叫兩次?

[英]Why is my setter called twice?

我正在使用JAX-RS,JPA和JAXB開發REST Web服務,用於管理游戲及其高分。 游戲具有以下屬性: nameurlhighscoreTableSize

什么我想要的簡短說明做:我createRow()在消耗JSON(一的JSON序列化的控制方法Game對象,類Game被帶注釋@XmlRootElement ),它調用靜態createRow()Game模型類中調用,並在其中調用setUrl() 問題是,由於某種原因,setter被兩次調用。

現在發生的是,如果在請求正文中發送的url對某種模式無效,則在“神秘”第一次調用后,它變為null ,第二次調用該setter時, if (url == null) ,而不是進入if (!matcher.matches()) ,而實際上后者是真實情況,因為我發送了錯誤鍵入的URL。

有人知道為什么會這樣嗎,我該如何解決?

先感謝您!

類游戲:

@Entity
@Table(name="games")
@XmlRootElement(name = "Game")
public class Game implements Serializable {

    //properties

    public void setUrl(String url) throws CustomWebServiceException {
        String regex = "^(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]";
        Pattern pattern = Pattern.compile(regex);

        System.out.println("URL: " + url);
        if ( url == null || url.length() == 0) {
          throw new CustomWebServiceException(Response.Status.BAD_REQUEST, new ErrorMessage("The url of the game is mandatory!"));
        } else {
          Matcher matcher = pattern.matcher(url);
          if (!matcher.matches()) { 
            throw new CustomWebServiceException(Response.Status.BAD_REQUEST, new         ErrorMessage("The url is invalid! Please check its syntax!"));
          } else {
            this.url = url;
          }
        }
    }

    public static Response createRow(EntityManager em, UserTransaction ut, String name, Game gameData) throws Exception {

        ut.begin();

        Game _game = em.find(Game.class, name);

        if (_game != null) {
          Util.tryRollback(ut);
          ErrorMessage errorMessage = new ErrorMessage(
              "The game with name " + name
              + " already exists in the database!");
          throw new CustomWebServiceException(Response.Status.CONFLICT,
              errorMessage);
        }

        String url = gameData.getUrl();
        Integer highscoreTableSize = gameData.getHighscoreTableSize();

        Game newGame = new Game();
        newGame.setName(name);
        newGame.setUrl(url);
        newGame.setHighscoreTableSize(highscoreTableSize);

        em.persist(newGame);

        // force the persistence manager to save data to DB
        ut.commit();

        if (highscoreTableSize == null) {
           highscoreTableSize = 7;
        }

        SuccessfulRequestMessage succesfulRequestMessage = new SuccessfulRequestMessage(
            " Game entry created with name: " + name
            + ", url: " + url + " and highscoreTableSize: " + highscoreTableSize
            + ".");
        return Response.status(Status.CREATED).entity(succesfulRequestMessage).type(MediaType.APPLICATION_JSON).build();
    }
}

控制器:

@PUT
@Path("/{name}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response createRow(
  @PathParam("name") String name, 
  Game gameData) throws CustomWebServiceException {

    try {
      return Game.createRow(em, ut, name, gameData);
    } catch (SystemException | NotSupportedException | IllegalStateException | SecurityException | HeuristicMixedException
        | HeuristicRollbackException | RollbackException e) {
      Util.tryRollback(ut);
      ErrorMessage errorMessage = new ErrorMessage(
          "Error when trying to create entry:" + e.toString()
          + " with message: " + e.getMessage());
      throw new CustomWebServiceException(
      Response.Status.INTERNAL_SERVER_ERROR, errorMessage);
    } catch (CustomWebServiceException e) {
       throw e;
    } catch (Exception e) {
      Util.tryRollback(ut);
      ErrorMessage errorMessage = new ErrorMessage(
          "During creation of game data, the following error(s) was(were) encountered: "
              + e.toString());
      throw new CustomWebServiceException(Response.Status.BAD_REQUEST,
          errorMessage);
    }
}

好吧,應該根據您的代碼兩次調用它。 在反序列化過程中一次,然后您自己完成一次:

newGame.setUrl(url);

在模型和表示上使用相同的類通常是個壞主意。 恕我直言,你應該做什么:

  • 將“ JSON”游戲與保存在數據庫中的對象分開
  • 不要在設置員中進行驗證。 有一個Spring Validation 使用它來確保您的JSON對象有效,然后直接進入數據庫。
  • 您可以使用推土機將模型對象自動轉換為制圖表達對象,反之亦然

編輯:不使用任何庫,最簡單的操作是將驗證移至控制器中的方法:

void validateInput(Game game) throws Exception {
  if (game == null) {
   throw new Exception("Game object is not present in the request");
  }
  if (game.getUrl() == null || !game.maches({some-fancyreg-exp}) {
   throw new Exception("Game URL is not valid");
  }
  //etc, check the rest of the fields
}

在控制器中調用validateInput(game)。 之后,您可以確保輸入有效。 快速又臟。 讓二傳手成為二傳手。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM