Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么我的二传手要打两次电话?_Java_Rest_Jaxb_Jax Rs_Unmarshalling - Fatal编程技术网

Java 为什么我的二传手要打两次电话?

Java 为什么我的二传手要打两次电话?,java,rest,jaxb,jax-rs,unmarshalling,Java,Rest,Jaxb,Jax Rs,Unmarshalling,我正在开发一个RESTWeb服务,使用JAX-RS、JPA和JAXB来管理游戏及其高分。游戏具有以下属性:name、url和highscoreTableSize 我尝试做的一个简短描述:我在控制器中有createRow()方法,该方法使用JSON(一个Game对象的JSON序列化,类Game被注释为@XmlRootElement),它从Game模型类调用静态createRow(),在它内部调用setUrl()。问题是,出于某种原因,二传手被称为两次 现在发生的情况是,如果请求主体中发送的url对

我正在开发一个RESTWeb服务,使用JAX-RS、JPA和JAXB来管理游戏及其高分。游戏具有以下属性:
name
url
highscoreTableSize

我尝试做的一个简短描述:我在控制器中有
createRow()
方法,该方法使用JSON(一个
Game
对象的JSON序列化,类
Game
被注释为
@XmlRootElement
),它从
Game
模型类调用静态
createRow()
,在它内部调用
setUrl()
。问题是,出于某种原因,二传手被称为两次

现在发生的情况是,如果请求主体中发送的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);
    }
}
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
}

嗯,它应该按照您的代码调用两次。在反序列化期间和您自己进行反序列化时:

newGame.setUrl(url);
一般来说,将同一类用于模型和表示是一个坏主意。 IMHO,你应该做什么:

  • 将“JSON”游戏与保存在数据库中的对象分开
  • 不要在setter中进行验证。这是有道理的。使用它来确保JSON对象有效,然后直接进入数据库
  • 可以使用推土机将模型对象自动转换为表示对象,反之亦然
编辑: 不使用任何库,您可以做的最简单的事情是将验证移动到控制器中的方法:

@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);
    }
}
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(游戏)。之后,您可以确保输入是有效的。又快又脏。让设定者成为设定者。

你有什么建议?使用弹簧或推土机并不是一个真正的选择。这个web服务有教育目的,Spring和Dozer还没有被研究过。JAXB什么时候第一次调用我的setter?它在创建
游戏gamaData
参数时会这样做吗?@SorinAdrianCarbunaru-yup。解析响应并将结果填充到新的游戏对象中。这是二传手被叫来的时候,嗯?什么反应?我猜您引用了请求主体中的JSON字符串,不是吗?