我正在开发一个REST Web服务,使用JAX-RS,JPA和JAXB来管理游戏及其高分。游戏具有以下属性:name
,url
和highscoreTableSize
。
我正在尝试做的简短描述:我在控制器中使用createRow()
方法,该方法使用JSON(Game
对象的JSON序列化,类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);
}
}
答案 0 :(得分:0)
好吧,应根据您的代码调用两次。在反序列化期间和自己完成之后:
newGame.setUrl(url);
对于模型和表示使用相同的类通常是一个坏主意。 恕我直言,你应该做什么:
修改强> 不使用任何库,最简单的方法是将验证移动到控制器中的方法:
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(游戏)。之后,您可以确定输入有效。又脏又脏。让setter成为setters。