0

I have two java models as player and team. I have a controller class. I get an error when I send a post request via ajax from the user interface. I've solved errors like CORS. But there is an error I can't solve; The knockout.js debug error and the post request are not occurring. There is no change in my database. I shared the model classes, the controller class, the html and javascriptfiles.

What do I need to change? Could you help?

Player Model

@Entity
@Table(name = "player")
public class Player{

    @Id
    @GeneratedValue
    @NotNull
    @Column
    private int id;

    @NotNull
    @Column
    private String playerName;

    @NotNull
    @Column
    private String playerSurname;

    @Column
    private int playerAge;



    public String getPlayerName() {
        return playerName;
    }

    public void setPlayerName(String playerName) {
        this.playerName = playerName;
    }

    public String getPlayerSurname() {
        return playerSurname;
    }

    public void setPlayerSurname(String playerSurname) {
        this.playerSurname = playerSurname;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getPlayerAge() {
        return playerAge;
    }

    public void setPlayerAge(int playerAge) {
        this.playerAge = playerAge;
    }
}

Team Model

@Entity
@Table(name = "team")
public class Team {

    @Id
    @GeneratedValue
    @NotNull
    @Column
    private int id;

    @NotNull
    @Column
    private String teamName;

    @Column
    private String teamCountry;

    public Team(){
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTeamName() {
        return teamName;
    }

    public void setTeamName(String teamName) {
        this.teamName = teamName;
    }

    public String getTeamCountry() {
        return teamCountry;
    }

    public void setTeamCountry(String teamCountry) {
        this.teamCountry = teamCountry;
    }

    @ManyToOne
    private Player player;

    public Player getPlayer() {
        return player;
    }

    public void setPlayer(Player player) {
        this.player = player;
    }
}

Controller

@CrossOrigin(origins = "http://localhost:8000/")
@RestController
public class TeamController {
    @Autowired
    PlayerRepository playerRepository;
    @Autowired
    TeamRepository teamRepository;

    @RequestMapping("/")
    public void main() {

        //create players by manual
        Player messi = new Player();
        Player ronaldo = new Player();
        Player ozil = new Player();

        messi.setPlayerName("Lionel");
        messi.setPlayerSurname("Messi");
        messi.setPlayerAge(31);

        ronaldo.setPlayerName("Cristiano");
        ronaldo.setPlayerSurname("Ronaldo");
        ronaldo.setPlayerAge(32);

        ozil.setPlayerName("Mesut");
        ozil.setPlayerSurname("Ozil");
        ozil.setPlayerAge(29);

        this.playerRepository.save(messi);
        this.playerRepository.save(ronaldo);
        this.playerRepository.save(ozil);

        //create teams by manual    
        Team barcelona = new Team();
        Team juventus = new Team();
        Team arsenal = new Team();

        barcelona.setTeamName("Barcelona");
        barcelona.setTeamCountry("Spain");
        barcelona.setPlayer(messi);

        juventus.setTeamName("Juventus");
        juventus.setTeamCountry("Italy");
        juventus.setPlayer(ronaldo);

        arsenal.setTeamName("Arsenal");
        arsenal.setTeamCountry("England");
        arsenal.setPlayer(ozil);

        this.teamRepository.save(barcelona);
        this.teamRepository.save(juventus);
        this.teamRepository.save(arsenal);

    }   

    //**PLAYER**
    @GetMapping(value="/getAllPLayers")
    public List<Player> getAllPlayers(){
        return playerRepository.findAll();
    }

    @PostMapping(value="getPlayerByName")
    public List<Player> getPlayerByName(@RequestParam("playerName") String playerName){
        return playerRepository.findByPlayerName(playerName);
    }

    @PostMapping(value="getPlayerBySurname")
    public List<Player> getPlayerBySurname(@RequestParam("playerSurname") String playerSurname){
        return playerRepository.findByPlayerSurname(playerSurname);
    }   

    @PostMapping(value="getPlayerByAge")
    public List<Player> getPlayerByAge(@RequestParam("playerAge") int playerAge){
        return playerRepository.findByPlayerAge(playerAge);
    }

    @PostMapping(value="createNewPlayer")
    public Player createNewPlayer(@Valid @RequestBody Player player) {
        return playerRepository.save(player);
    }


    //**TEAM**
    @GetMapping(value="/getAllTeams")
    public List<Team> getAllTeams(){
        return teamRepository.findAll();
    }

    @PostMapping(value = "/getTeamsByName")
    public List<Team> getTeamByName(@RequestParam("teamName") String teamName){
        return teamRepository.findByTeamName(teamName);
    }

    @PostMapping(value = "/getTeamsByCountry")
    public List<Team> getTeamByCountry(@RequestParam("teamCountry") String teamCountry){
        return teamRepository.findByTeamCountry(teamCountry);
    }

@PostMapping(value="/createNewTeam")
public Team createNewTeam(@Valid @RequestBody Player player,@RequestBody Team team) {
    playerRepository.save(player);
    team.setPlayer(player);
    return teamRepository.save(team);
}

}

Config

@Configuration
@EnableWebMvc
public class WebConfig implements Filter,WebMvcConfigurer {


    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**");
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
      HttpServletResponse response = (HttpServletResponse) res;
      HttpServletRequest request = (HttpServletRequest) req;
      System.out.println("WebConfig; "+request.getRequestURI());
      response.setHeader("Access-Control-Allow-Origin", "*");
      response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
      response.setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With,observe");
      response.setHeader("Access-Control-Max-Age", "3600");
      response.setHeader("Access-Control-Allow-Credentials", "true");
      response.setHeader("Access-Control-Expose-Headers", "Authorization");
      response.addHeader("Access-Control-Expose-Headers", "USERID");
      response.addHeader("Access-Control-Expose-Headers", "ROLE");
      response.addHeader("Access-Control-Expose-Headers", "responseType");
      response.addHeader("Access-Control-Expose-Headers", "observe");
      System.out.println("Request Method: "+request.getMethod());
      if (!(request.getMethod().equalsIgnoreCase("OPTIONS"))) {
          try {
              chain.doFilter(req, res);
          } catch(Exception e) {
              e.printStackTrace();
          }
      } else {
          System.out.println("Pre-flight");
          response.setHeader("Access-Control-Allow-Origin", "*");
          response.setHeader("Access-Control-Allow-Methods", "POST,GET,DELETE,PUT");
          response.setHeader("Access-Control-Max-Age", "3600");
          response.setHeader("Access-Control-Allow-Headers", "Access-Control-Expose-Headers"+"Authorization, content-type," +
          "USERID"+"ROLE"+
                  "access-control-request-headers,access-control-request-method,accept,origin,authorization,x-requested-with,responseType,observe");
          response.setStatus(HttpServletResponse.SC_OK);
      }
    }
}

Player Repo

public interface PlayerRepository extends JpaRepository<Player, Integer>{
    List<Player> findByPlayerName(String playerName);
    List<Player> findByPlayerSurname(String playerSurname);
    List<Player> findByPlayerAge(int playerAge);
}

Team Repo

public interface TeamRepository extends JpaRepository<Team, Integer>{
    List<Team> findByTeamName(String teamName);
    List<Team> findByTeamCountry(String teamCountry);

}

POST HTML Page

<!DOCTYPE HTML>
<html>
<head>
      <title>Team Management</title>
      <meta charset="utf-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link rel="stylesheet"
          href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" />
    <script
            src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script
            src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js"></script>
    <script
            src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js"></script>
            <script src="js/restGetPlayer.js"></script>
            <script src="js/restGetTeam.js"></script>
            <script src="js/postTeam.js"></script>
</head>
<body>

<div class="container">
    <h3 style="color: darkolivegreen" align="center">Create a new team</h3>

    <div class"main-block>
        <form id="teamForm" class="form-inline" style="margin:20px 20px 20px 20px">
        <div class="form-group">
                <label for="playerName" style="margin-left:20px; margin-right:5px">Player Name:</label>
                <input type="text" class="form-control" id="playerName" placeholder="Enter player name"/>
        </div>  
        <br>
        <div class="form-group">
                <label for="playerSurname" style="margin-left:20px; margin-right:5px">Player Surname:</label>
                <input type="text" class="form-control" id="playerSurname" placeholder="Enter player surname"/>
        </div> 
        <div class="form-group">
                <label for="playerAge" style="margin-left:20px; margin-right:5px">Player Age:</label>
                <input type="text" class="form-control" id="playerAge" placeholder="Enter player age"/>
        </div>       
        <br style="clear: both;">
            <div class="form-group">
                <label for="teamName" style="margin-right:5px">Team Name:</label>
                <input type="text" class="form-control" id="teamName" placeholder="Enter team name"/>
            </div>
            <br>
            <div class="form-group">
                <label for="teamCountry" style="margin-left:20px; margin-right:5px">Team Country:</label>
                <input type="text" class="form-control" id="teamCountry" placeholder="Enter team country"/>
            </div>          
            <br>
            <hr>
            <button type="submit" class="btn btn-default" style="margin-left:20px; margin-right:5px" >Submit Team</button>
        </form>
    </div>

    <div class="col-sm-7" style="margin:20px 0px 20px 0px">
        <button id="getAllTeams" class="btn btn-primary">Get Team Information</button>
        <div id="getResultDiv3" style="padding:20px 10px 20px 50px">
          <ul class="list-group">
        </ul>
      </div>
    </div>
</div>
<style>
.container {
  max-width: 400px;
  width: 100%;
  margin: 0 auto;
  position: relative;
}
#contact {
  background: #F9F9F9;
  padding: 25px;
  margin: 150px 0;
  box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2), 0 5px 5px 0 rgba(0, 0, 0, 0.24);
}
</style>
<script type="text/javascript" src="js/libs/require/require.js"></script>
<script type="text/javascript" src="js/main.js"></script>
</body>
</html>

AJAX POST

$( document ).ready(function() {

    $("#teamForm").submit(function(event) {
        event.preventDefault();
        ajaxPost();
    });

    function ajaxPost(){

        var formData = {
            playerName :  $("#playerName").val(),
            playerSurname :  $("#playerSurname").val(),
            playerAge :  $("#playerAge").val(),
            teamName : $("#teamName").val(),
            teamCountry :  $("#teamCountry").val()
        }

        $.ajax({
            type : "POST",
            contentType : "application/json",
            url : "http://localhost:8080" + "/createNewTeam",
            data : JSON.stringify(formData),
            dataType : 'json',

            success: function(result){
                alert("Teams loaded!");
                console.log(result);
                $('#getResultDiv3 ul').empty();
                var tableTitle = "<h2><strong>Team List</strong></h2>";
                var teamList = "<table border='1'>";
                teamList += "<tr><td><strong>Team Name</strong></td><td><strong>Team Country</strong></td><td><strong>Player Name</strong></td><td><strong>Player Surname</strong></td><td><strong>Player Age</strong></td></tr>";

                $.each(result, function(i, teams){
                    teamList +="<tr>";
                    teamList +="<td>"+teams.teamName +"</td>";
                    teamList +="<td>"+teams.teamCountry+"</td>";
                    teamList +="<td>"+teams.player.playerName+"</td>";
                    teamList +="<td>"+teams.player.playerSurname+"</td>";
                    teamList +="<td>"+teams.player.playerAge+"</td>";
                    teamList +="</tr>";
                });
                teamList +="</table>";
                $('#getResultDiv3').append(tableTitle, teamList)
                console.log("Success: ", result);
        },
            error : function(e) {
                $("#getResultDiv3").html("<strong>Error</strong>");
                console.log("ERROR: ", e);
            }
        });

        resetData();
    }

    function resetData(){
        $("#playerName").val("");
        $("#playerSurname").val("");
        $("#playerAge").val("");
        $("#teamName").val("");
        $("#teamCountry").val("");

    }
})

MainController.js

/**
 * @license
 * Copyright (c) 2014, 2019, Oracle and/or its affiliates.
 * The Universal Permissive License (UPL), Version 1.0
 */
/*
 * Your application specific code will go here
 */
define(['ojs/ojresponsiveutils', 'ojs/ojresponsiveknockoututils', 'knockout', 'ojs/ojknockout'],
  function(ResponsiveUtils, ResponsiveKnockoutUtils, ko) {
     function ControllerViewModel() {
       var self = this;

      // Media queries for repsonsive layouts
      var smQuery = ResponsiveUtils.getFrameworkQuery(ResponsiveUtils.FRAMEWORK_QUERY_KEY.SM_ONLY);
      self.smScreen = ResponsiveKnockoutUtils.createMediaQueryObservable(smQuery);

      // Header
      // Application Name used in Branding Area
      self.appName = ko.observable("Oracle JET + REST API");
      // User Info used in Global Navigation area
      self.userLogin = ko.observable("admin@oracle.com");

      // Footer
      function footerLink(name, id, linkTarget) {
        this.name = name;
        this.linkId = id;
        this.linkTarget = linkTarget;
      }
      self.footerLinks = ko.observableArray([
        new footerLink('About Oracle', 'aboutOracle', 'http://www.oracle.com/us/corporate/index.html#menu-about'),
        new footerLink('Contact Us', 'contactUs', 'http://www.oracle.com/us/corporate/contact/index.html'),
        new footerLink('Legal Notices', 'legalNotices', 'http://www.oracle.com/us/legal/index.html'),
        new footerLink('Terms Of Use', 'termsOfUse', 'http://www.oracle.com/us/legal/terms/index.html'),
        new footerLink('Your Privacy Rights', 'yourPrivacyRights', 'http://www.oracle.com/us/legal/privacy/index.html')
      ]);
     }

     return new ControllerViewModel();
  }
);

Picture 1: Adding Player

Picture 2: ERROR log After add player

Picture 3: MySQL player table did not any change

ultum
  • 104
  • 1
  • 10
  • First there is an error in the applyBinding, can you post the code (main.js)? Then it seems strange to me the "data: JSON.stringify(formData)", I think you should write "data: formData" without converting it to json string. – Bludev Aug 01 '19 at 08:56

1 Answers1

0

Answering your question, it is not doing anything because you are not sending the parameter Player (that must be valid) due you are using a form this is not the way you should do it. (request params are send via url and your form should do it via @RequestBody)

Check this post for information. Can I use @Requestparam annotation for a Post request?

I would do something like this:

On my controller due I can have only one @RequestBody but my form sends an object containing data for multiple types of an object I would do a Dto

Something like this:

@PostMapping(value="/createNewTeam")
    public Team createNewTeam(@Valid @RequestBody PayloadDto payloadDto) {
        final Player player = new Player();
        player.setPlayerName(payloadDto.playerName);
        // fill player information
        final Team team = new Team();
        // fill team information... 
        playerRepository.save(player);
        return teamRepository.save(team);
    }

Your PayloadDto object must contain all attributes you are sending..

public class PayloadDto{

  @JsonProperty("playerName")
  public String playerName;
  @JsonProperty("playerSurname")
  public String playerSurname;
  // .. more player and team properties 
}

Be sure that the jsonProperty("propertyName) holds the same name you are using when sending the information

jpganz18
  • 5,508
  • 17
  • 66
  • 115
  • what should i change? – ultum Aug 01 '19 at 09:00
  • i forgot to add player and team repositories, then i added the question. – ultum Aug 01 '19 at 10:25
  • i used JpaRepository for the get,post,update,delete. How do I make changes to dto? – ultum Aug 01 '19 at 10:27
  • you dont, your jpa repository will use the objects that represent the entity, a DTO (data transfer object) will work as intermediate between your frontend and your controller, once in your controller you create same objects you use for your repository and invoke the repository.save in the same way – jpganz18 Aug 01 '19 at 11:19
  • I have never used DTO before. Should I open a new class and call the player and team attributes as 'public' ? How will this player and team values interact with the database? – ultum Aug 01 '19 at 11:27
  • You can read more about DTO in multiple places, this for example https://softwareengineering.stackexchange.com/questions/171457/what-is-the-point-of-using-dto-data-transfer-objects Why you want to make public player and team objects? you have to encapsulate this logic as much as possible, avoid exposing it through your endpoint is also a good practice, thats why a DTO sounds good there. Player and Team willl keep interacting same way with your DB as they are doing now, if you check the code, you create a new player and team object from the DTO info, the rest goes on the same way. – jpganz18 Aug 01 '19 at 11:30
  • In your comment, there were public attributes within the Dto class. That's why I asked you. Do you know how I can do it with JpaRepository without using DTO? Without creating another class. – ultum Aug 01 '19 at 11:34
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/197344/discussion-between-jpganz18-and-mutlu). – jpganz18 Aug 01 '19 at 11:37