jjwt icon indicating copy to clipboard operation
jjwt copied to clipboard

Can't use setHeader(Header) because ambigous method call

Open kleewho opened this issue 9 years ago • 18 comments

Header is both a Header and a Map so this won't work:

Header header = new DefaultHeader();

String payloadWithoutPartner1 = Jwts.builder()
         .setClaims(claims)
         .signWith(SignatureAlgorithm.HS256, key)
         .setHeader(header)
         .compact();

Ambiguous method call. Both setHeader (Header) in JwtBuilder and setHeader(Map<String, Object>) in JwtBuilder match

kleewho avatar Sep 30 '16 08:09 kleewho

I don't understand the issue - this is standard Java method overloading, no? Can you please clarify the problem?

lhazlewood avatar Sep 30 '16 23:09 lhazlewood

Ah, don't instantiate DefaultHeader. Use Jwts.header() ?

Ordinarily you should not instantiate anything in the impl package directly.

lhazlewood avatar Sep 30 '16 23:09 lhazlewood

@lhazlewood using Jwts.header() doesn't change anything. Standard technique or not compiler won't know which overload version to use, cause both are applicable. This is the simplest thing you can paste and check for yourself:

@Test
    public void whatever() {
        Header header = Jwts.header();

        String payloadWithoutPartner1 = Jwts.builder()
                .setHeader(header)
                .compact();
    }

kleewho avatar Oct 03 '16 08:10 kleewho

@lhazlewood Have you tried to compile that snippet?

kleewho avatar Dec 01 '16 13:12 kleewho

Hi, am'i the same problem, Are there any solution ?

WebertonSilva avatar Jan 24 '17 20:01 WebertonSilva

Yeah, do not use it Header, but just Map<String, Object>. Please note that this map have to be mutable, so do not even try guava or something

kleewho avatar Jan 25 '17 15:01 kleewho

@lhazlewood at least 3 users thinks it is a bug. Could you please try to compile my snippet so you can see it for yourself?

kleewho avatar Jan 25 '17 15:01 kleewho

Same problem here. I ended up using setHeaderParam() which is simpler anyways.

nateridderman avatar Feb 10 '17 17:02 nateridderman

Casting to map .setHeader((Map<String, Object>) header) works

Like the last entry stated, I used setHeaderParam, instead.

robrez avatar Apr 10 '17 15:04 robrez

This seems to be a bug in the definition of the interface JwtBuilder. I don't think it is possible to call the method setHeader(x) when x is of type Header. This is because a Header is also a Map<String,Object>, and so Java won't know whether to call the setHeader method with type Header or with type Map<String,Object>.

Well, casting a Header to Map<String, Object> as robrez did might work, but you are still not calling the setHeader with parameter Header, you are calling setHeader with parameter Map<String,Object>.

So I think the code that defines setHeader( Header x) is dead code as it can never be called.

This sort of makes the whole methods of Header building with Jwts.header() and Jwts.jwsHeader() pointless in the sense that you can get a Header, and then put what you want into the header, but then you need to cast it make to a Map<String,Object> in order to build a token with your header... so why not just start out with a Map<String,Object> that is NOT an actual Header, and use that?

Or am I missing something?

(PS I ended up using setHeaderParam as well.

hong-yi-en avatar Aug 12 '17 05:08 hong-yi-en

@hong-yi-en spot on. You can't call it with Header as compiler will complain.

@lhazlewood I guess any user that have commented here can fix that (including me) so just tell us how would you like it to be solved and we can move on

kleewho avatar Aug 21 '17 08:08 kleewho

It is not possible to use headers created with Jwts.header() in the builder without any compilation warnings or errors.

mindhaq avatar Oct 30 '18 19:10 mindhaq

The only benefit I see of using Header and then casting in the setHeader() method is the use of type-safe getters and setters as stated in the Header Javadocs.

JwsHeader<?> header = Jwts.jwsHeader();
header.setKeyId("key_id");
header.setType("the_type");
...
Jwts.builder().setHeader((Map<String, Object>)header);

daveneiman avatar Nov 28 '18 21:11 daveneiman

I would consider using these type-safe methods a very good thing. Otherwise - why is there even a class JwsHeader?

mindhaq avatar Nov 29 '18 10:11 mindhaq

Just following this up - yes, the API should be cleaned up to avoid this confusion. Thanks for reporting and confirming everyone. We'll track this for a future release, but it remains to be seen if this would require backwards-incompatible changes. If so, those changes would have to wait for 1.0, otherwise, we'll come up with a fix as best as is possible.

lhazlewood avatar Jul 15 '19 19:07 lhazlewood

Also note: currently the JJWT API uses method names of setHeader and setHeaderParam to mirror with that JWT RFC calls these concepts.

An impedance mismatch here is that the spec calls the entire JSON object with all of its name/value pairs as the Header (singular) and each name/value pair within it as a header parameter, but almost all Java developers refer to these things collectively as 'headers' (plural), and each individual one as a 'header', likely due to HTTP taxonomy.

Perhaps a simplification for Java idioms (rather than RFC taxonomy) can be used:

<T> JwtBuilder setHeader(String name, T value) and JwtBuilder setHeaders(Map<String, ?> params)

I'm not sure if this is desirable or not however. Using different names than the spec could cause confusion for some. I'm curious what the JJWT community prefers.

Another challenge with changing taxonomy is that corresponding interfaces reflect the specification's taxonomy (as they should really), so changing interfaces might be a no-go. We might be forced to keep the existing nomenclature, which might not be such a bad thing. I think perhaps the real issue is ensuring there are no compiler warnings/errors.

lhazlewood avatar Jul 15 '19 19:07 lhazlewood

Any update on this issue? Its still persist in the latest version.

pethaniakshay avatar Mar 21 '21 07:03 pethaniakshay

It's likely something that will need to wait for a breaking API change @pethaniakshay, but for now, you should be able to cast the param to force the use of the expected method. (or one of the other header related methods)

I just flagged the issue with the "1.0" milestone as well

bdemers avatar Mar 22 '21 20:03 bdemers

Many years have passed and this problem has not been solved. Is this funny?

mmm8955405 avatar Oct 26 '22 01:10 mmm8955405

I heard on slack that 1.0 development was started.

bmarwell avatar Mar 11 '23 12:03 bmarwell

This fix has been merged to master.

lhazlewood avatar Aug 11 '23 20:08 lhazlewood