0

I have a controller method in spring boot:

@PostMapping(produces = "text/html")
public String create(@Valid myDTO myDTO, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest) {
    // Omissions
   
    return "redirect:/blue/tar/";
}

I have a dto:

public class MyDTO {

    private Long id;
    private List<FooBar> objects;

    public MyDTO(Long id, List<FooBar> objects) {
        this.id = id;
        this.objects = objects;
    }

    public Long getId() {
        return id;
    }

    public List<FooBar> getObjects() {
        return objects;
    }
}

And I have a converter, which i have added to the converterRegistry in spring:

private Converter<String, FooBar> getStringToLegalEntityConverter() {
    return new org.springframework.core.convert.converter.Converter<>() {
        public FooBar convert(@NotNull String id) {
            return //* convert id to FooBar structure*//
        }
    };
}

My web form send form data. E.g:

fooBar: 1
fooBar: 3
fooBar: 4

And the above code handles this perfectly. The converter is called three times with 1, 3 and 4. The result a bit magically appears as a list with three FooBar objects in the dto in the controller.

The above works.

I attempted to use a map in MyDTO instead. Spring complains that there is no converter from String -> Map.

If i add one (which feels wrong, since there was no converter from String -> List before), it only enters the converter once with the last value. (4, in the example above).

So is there a solution here to get spring to allow me to manually convert a series of form params to a map in such a way that they end up in a DTO like that?

Below is my attempt which fails. Since spring only attempts to convert one value to fit in the map in the DTO. I would have needed the converter to be called with all the form parameters at once:

private Converter<String, Map<Long, FooBar>> attempt() {
    return new org.springframework.core.convert.converter.Converter<>() {
        public Map<Long, FooBar> convert(@NotNull String aString) {
            
            /* Say if aString is the formparameters as "1,3,4" then i'd turn those into keys and then fetch their values from a db */
            return /* The map */
        }
    };
}

Similar but I don't think the answers there are applicable: How to get Form data as a Map in Spring MVC controller?

Adam
  • 2,845
  • 2
  • 32
  • 46
  • What do you want to convert to what that isn't clear. What have you tried. For a collection it is easy, as it is just a collection of elements. For a map it isn't as what should be the key? What should be the value? – M. Deinum Jan 05 '22 at 13:34
  • Yes the trickyness there I'd expect to have to solve in the converter. And for that to work I have to get all the form params as input to the converter. So I can manually construct the map. But maybe it is impossible to do it this way then if spring says it wants String -> Map conversion and only gives the the las form parameter(and not all of them). – Adam Jan 05 '22 at 13:51
  • I tried with two converters at one point I think. on String -> FooBar and one List -> Map... but spring would not magic that together – Adam Jan 05 '22 at 13:53
  • As stated it isn't clear how to convert a single string to a map entry what should be the key and what the value. Why not simply map to a collection (`List`) and then create a getter that does the conversion. – M. Deinum Jan 05 '22 at 15:12
  • Updated code in Q with example of map creation. The underlaying reason I want to have a map is because I failed to solve https://stackoverflow.com/questions/70590831/make-taglib-available-in-spring-jspx. And the other answer for this Q: https://stackoverflow.com/questions/1490139/evaluate-list-contains-string-in-jstl had me try the map route. So the reason I want a map is that I couldn't import a taglib i'd made, and a map could've been a workaround. But ofcourse I'm in it for the knowledge at this point. I went with the third workaround for the actual problem. – Adam Jan 06 '22 at 21:16
  • The 'real reason' is that there is quite a large 'swathe' of code surronding this, and doing it like this would 'upset' that code the least with the changes required, whilst not making it more complex. But then again if this map thing involves ugly hacks and is not straightforward, then the way It was solved is better anyway. This solution has an uphill battle, it needs to be extraordinarily crisp to be better than what is in place atm. – Adam Jan 06 '22 at 21:22
  • What is it that you are trying to solve actually? How on earth did you get from cannot include/use a taglib to trying to shoehorn stuff into a map. Also as stated just writing a getter that converts the list into a map will just work and you can just call that from your JSP (also why are you even still on JSPs?). – M. Deinum Jan 07 '22 at 07:39
  • It's all legacy code. I do think that writing a getter like that would work. I want a contains-function in the jsp, tamersalama's answer in one of the linked issues suggested a trick with a map. I'll try it out with a getter! – Adam Jan 07 '22 at 08:03
  • How is creating a getter that creates the map or a getter that returns a pre-existing map different from using a contains function? Why wouldn't you be able to use the contains function on a list (you shouldn't be using th fn:contains as that only works for strings not other objects. You can always write a utility method to do the contains check you want. It looks like you are trying to make a very complex solution for a simple problem. – M. Deinum Jan 07 '22 at 08:09
  • 'You can always write a utility method to do the contains check you want.' I was under the impression that I needed to make the taglib-thing to be able to access such a function? The Q: https://stackoverflow.com/questions/1490139/evaluate-list-contains-string-in-jstl really was exactly my original problem, the top 3 answers there, check em out, nr 2 and nr 3 (+ your getter thing) works for me. – Adam Jan 07 '22 at 08:29
  • You don't need a taglib to execute an expression and you can just call a function in a JSP. – M. Deinum Jan 10 '22 at 06:35

0 Answers0