2

After 15 hours of trial and horror I've decided to share my issues with the world, because quite frankly, I have no idea how to solve my problem anymore:

I've created a custom form for users to check checkboxes and press a save button: Here's the snippet of the relevant code:

<form th:action="@{/profile}" action="/profile" th:object="${profileModel}" method="POST">
    <div class="row" style="margin-left: 5px;"><h4>Select</h4></div>

        <div class="row">

        <!-- Barbell -->
            <section class="panel panel-default panel-equipment col-md-3">
                <header class="panel-heading panel-heading-profileform">
                    <h3 class="panel-title"><b>Barbell</b></h3>
                </header>
                <div class="col-md-12">
                    <div><input type="checkbox" th:field="*{equipment.barbellLight}" th:value="1">   Light</input></div>
                    <div><input type="checkbox" th:field="*{equipment.barbellMedium}" th:value="1">   Medium</input></div>
                    <div><input type="checkbox" th:field="*{equipment.barbellHeavy}" th:value="1">   Heavy</input></div>
                </div>
            </section>
        </div>
    </div>
</form>

My controller: The request:

@RequestMapping(value = "/profilestage", method=RequestMethod.POST)
public String updateProfileStage(@ModelAttribute ProfileModel profileModel, Model model){

    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    String username = auth.getName();
    model.addAttribute("signedin", true);
    model.addAttribute("username", username.substring(0, 1).toUpperCase() + username.substring(1));

    UserEntity user = userService.findByUsername(username);
    ProfileEntity profile = user.getProfile();

    model.addAttribute("profileModel", ModelEntityConvertor.profileEntityToModel(profile));

    return "profile_new";
}

This isn't all of the controller, but as far as you need to know, I've debugged all of this code VERY thoroughly and the profileModel going in, the one used in th:object, is never null and always has all required fields set (in my case all 0's).

The form is posting to this controller:

@RequestMapping(value = "/profile", method=RequestMethod.POST)
public String updateProfile(@ModelAttribute ProfileModel profileModel, Model model){

    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    String username = auth.getName();
    UserEntity user = userService.findByUsername(username);
    ProfileEntity profile = user.getProfile();
    profile.setEquipment(ModelEntityConvertor.equipmentModelToEntity(profileModel.getEquipment(), profile.getEquipment()));

    profileService.updateProfile(profile);

    return this.getProfile(model);
}

This controller is never reached whenever my application decides to not work, but whenever it IS reached, it works like a charm and works exactly as it should.

The big issue I'm trying to wrap my head around, is the fact that all of this occasionally works.. One minute I run the code, no problems. I then rerun the exact same code, try doing this with another user, or both and after clicking on save spring's default error page is displayed. No error message is provided anywhere...

I've tried:

  • cleaning the project
  • closing eclipse
  • rebuilding project entirely
  • working in chrome's developer mode (I always do this, any changes in css are always displayed)
  • added both spring.template.cache: false and spring.thymeleaf.cache: false to properties

I honestly don't understand what I'm doing wrong and will REALLY appreciate your help =)

Thnx in advance for reading my wall of text and apologies for the latter. If any more of my code is required, I'm here non-stop.

vphilipnyc
  • 6,607
  • 6
  • 44
  • 70
Roel Strolenberg
  • 2,822
  • 1
  • 12
  • 27
  • 1
    Perhaps try setting this to DEBUG in your logger: `org.springframework.web` and `org.spring.web.context` and try to reproduce your issue. It may give you some insight about pages that are not named correctly, etc. – vphilipnyc Feb 19 '16 at 22:02
  • 1
    Also, not sure about your design but have your tried changing the param to `method=RequestMethod.GET` on your first controller block? Is a POST intended there? – vphilipnyc Feb 19 '16 at 22:10
  • I'm relatively new to this and you are correct, it should be a GET, obviously. I've set the logging levels and I actually get an error now! I checked 1 out of 3 checkboxes -> null on 2 elements of my ProfileModel in the second controller. I check all 3, works like a charm! Guess I've figured out my problem =) Need to set the other values to 0 as I'm using primitves – Roel Strolenberg Feb 19 '16 at 22:23

1 Answers1

2

1) Change the method=RequestMethod.POST to method=RequestMethod.GET in your first Controller block.

Further background on GET vs POST (not needed for OP, but for future readers)

2) Setting this to DEBUG in your logger: org.springframework.web and org.spring.web.context may also shed further insight into which pages are getting called.

3) Add a BindingResult to your method signature to default your primitives to zero. (See notes from OP in comments.)

Community
  • 1
  • 1
vphilipnyc
  • 6,607
  • 6
  • 44
  • 70
  • Changing to GET doesn't resolve this issue unfortunately =( Adding the loggings did help a LOT however! I'm still facing the problem. In the first controller (now GET) i add a profileModel to the Model which is just a list of attributes (`private byte barbellLight;` etc) with value 0. However, if I click save after checking some checkboxes, all non-checked attributes are no longer 0, but null. As a byte is primitive and cannot be null, I get an exception. I still don't understand why the values of those attributes become null.. – Roel Strolenberg Feb 19 '16 at 23:07
  • Try using `th:checked` instead? http://stackoverflow.com/questions/28488202/check-inputs-with-type-checkbox-with-thymeleaf – vphilipnyc Feb 19 '16 at 23:17
  • I fixed my own problem by changing `public String updateProfileStage(@ModelAttribute ProfileModel profileModel, Model model)` to `public String updateProfile(@ModelAttribute("profileModel") ProfileModel profileModel,BindingResult result, Model model)`. The binding result over the profileModel ModelAttribute catches the errors and automatically sets the primitives to default (0). Add this fix to your answer @bphilipnyc and I will accept it =). Wouldn't have figured this out without your help! – Roel Strolenberg Feb 19 '16 at 23:19
  • Yes, that would make sense about the catching part. Will do – vphilipnyc Feb 19 '16 at 23:20