Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nonPublicPartOfAPI for MyTokenizer reported by revapi #4613

Closed
sbernard31 opened this issue Jul 4, 2024 · 3 comments
Closed

nonPublicPartOfAPI for MyTokenizer reported by revapi #4613

sbernard31 opened this issue Jul 4, 2024 · 3 comments

Comments

@sbernard31
Copy link

I'm using revapi, to check I respect semantic versioning in my project.

But it also checks some code smell about API.
When building my project, it report something wrong with jackson (which is one of my dependencies)

Report :

{
  "ignore": true,
  "code": "java.class.nonPublicPartOfAPI",
  "new": "class com.fasterxml.jackson.databind.type.TypeParser.MyTokenizer",
  "justification": "ADD YOUR EXPLANATION FOR THE NECESSITY OF THIS CHANGE"
   "classSimpleName": "MyTokenizer",
  "exampleUseChainInNewApi": "com.fasterxml.jackson.databind.type.TypeParser.MyTokenizer is used as parameter in method java.lang.IllegalArgumentException com.fasterxml.jackson.databind.type.TypeParser::_problem(com.fasterxml.jackson.databind.type.TypeParser.MyTokenizer, java.lang.String) <- field com.fasterxml.jackson.databind.type.TypeFactory._parser has the type com.fasterxml.jackson.databind.type.TypeParser <- com.fasterxml.jackson.databind.type.TypeFactory is used as parameter in method com.fasterxml.jackson.databind.JavaType com.fasterxml.jackson.databind.util.Converter<IN, OUT>::getInputType(com.fasterxml.jackson.databind.type.TypeFactory) <- com.fasterxml.jackson.databind.util.Converter<IN, OUT> is returned from method com.fasterxml.jackson.databind.util.Converter<java.lang.Object, java.lang.Object> com.fasterxml.jackson.databind.DatabindContext::converterInstance(com.fasterxml.jackson.databind.introspect.Annotated, java.lang.Object) throws com.fasterxml.jackson.databind.JsonMappingException @ com.fasterxml.jackson.databind.SerializerProvider <- com.fasterxml.jackson.databind.SerializerProvider is used as parameter in method com.fasterxml.jackson.annotation.JsonFormat.Value com.fasterxml.jackson.databind.ser.std.StdSerializer<T>::findFormatOverrides(com.fasterxml.jackson.databind.SerializerProvider, com.fasterxml.jackson.databind.BeanProperty, java.lang.Class<?>) @ com.fasterxml.jackson.databind.ser.ContainerSerializer<T> <- com.fasterxml.jackson.databind.ser.ContainerSerializer<T> is returned from method com.fasterxml.jackson.databind.ser.ContainerSerializer<?> com.fasterxml.jackson.databind.ser.ContainerSerializer<T>::withValueTypeSerializer(com.fasterxml.jackson.databind.jsontype.TypeSerializer) @ com.fasterxml.jackson.databind.ser.std.MapSerializer <- field com.fasterxml.jackson.databind.ser.AnyGetterWriter._mapSerializer has the type com.fasterxml.jackson.databind.ser.std.MapSerializer <- com.fasterxml.jackson.databind.ser.AnyGetterWriter is used as parameter in method void com.fasterxml.jackson.databind.ser.BeanSerializerBuilder::setAnyGetter(com.fasterxml.jackson.databind.ser.AnyGetterWriter) <- com.fasterxml.jackson.databind.ser.BeanSerializerBuilder is used as parameter in method com.fasterxml.jackson.databind.ser.BeanSerializerBuilder com.fasterxml.jackson.databind.ser.BeanSerializerModifier::updateBuilder(com.fasterxml.jackson.databind.SerializationConfig, com.fasterxml.jackson.databind.BeanDescription, com.fasterxml.jackson.databind.ser.BeanSerializerBuilder) <- com.fasterxml.jackson.databind.ser.BeanSerializerModifier is used as parameter in method com.fasterxml.jackson.databind.ser.SerializerFactory com.fasterxml.jackson.databind.ser.SerializerFactory::withSerializerModifier(com.fasterxml.jackson.databind.ser.BeanSerializerModifier) <- field com.fasterxml.jackson.databind.ObjectWriter._serializerFactory has the type com.fasterxml.jackson.databind.ser.SerializerFactory <- com.fasterxml.jackson.databind.ObjectWriter is returned from method com.fasterxml.jackson.databind.ObjectWriter com.fasterxml.jackson.databind.ObjectMapper::writerWithType(com.fasterxml.jackson.databind.JavaType) <- com.fasterxml.jackson.databind.ObjectMapper is used as parameter in method void org.eclipse.leshan.senml.json.jackson.SenMLJsonJacksonEncoderDecoder::<init>(org.eclipse.leshan.core.util.json.JacksonJsonSerDes<org.eclipse.leshan.senml.SenMLRecord>, com.fasterxml.jackson.databind.ObjectMapper) (method void org.eclipse.leshan.senml.json.jackson.SenMLJsonJacksonEncoderDecoder::<init>(org.eclipse.leshan.core.util.json.JacksonJsonSerDes<org.eclipse.leshan.senml.SenMLRecord>, com.fasterxml.jackson.databind.ObjectMapper) is part of the API)",
  "package": "com.fasterxml.jackson.databind.type",
  "classQualifiedName": "com.fasterxml.jackson.databind.type.TypeParser.MyTokenizer",
  "elementKind": "class",
  "newArchive": "com.fasterxml.jackson.core:jackson-databind:jar:2.17.1",
  "newArchiveRole": "supplementary",
},

nonPublicPartOfAPI is described here.

I copy/paste the exampleUseChainInNewApi here because this is the most important part to understand the issue :

"com.fasterxml.jackson.databind.type.TypeParser.MyTokenizer is used as parameter in method java.lang.IllegalArgumentException com.fasterxml.jackson.databind.type.TypeParser::_problem(com.fasterxml.jackson.databind.type.TypeParser.MyTokenizer, java.lang.String) <- field com.fasterxml.jackson.databind.type.TypeFactory._parser has the type com.fasterxml.jackson.databind.type.TypeParser <- com.fasterxml.jackson.databind.type.TypeFactory is used as parameter in method com.fasterxml.jackson.databind.JavaType com.fasterxml.jackson.databind.util.Converter<IN, OUT>::getInputType(com.fasterxml.jackson.databind.type.TypeFactory) <- com.fasterxml.jackson.databind.util.Converter<IN, OUT> is returned from method com.fasterxml.jackson.databind.util.Converter<java.lang.Object, java.lang.Object> com.fasterxml.jackson.databind.DatabindContext::converterInstance(com.fasterxml.jackson.databind.introspect.Annotated, java.lang.Object) throws com.fasterxml.jackson.databind.JsonMappingException @ com.fasterxml.jackson.databind.SerializerProvider <- com.fasterxml.jackson.databind.SerializerProvider is used as parameter in method com.fasterxml.jackson.annotation.JsonFormat.Value com.fasterxml.jackson.databind.ser.std.StdSerializer::findFormatOverrides(com.fasterxml.jackson.databind.SerializerProvider, com.fasterxml.jackson.databind.BeanProperty, java.lang.Class) @ com.fasterxml.jackson.databind.ser.ContainerSerializer <- com.fasterxml.jackson.databind.ser.ContainerSerializer is returned from method com.fasterxml.jackson.databind.ser.ContainerSerializer com.fasterxml.jackson.databind.ser.ContainerSerializer::withValueTypeSerializer(com.fasterxml.jackson.databind.jsontype.TypeSerializer) @ com.fasterxml.jackson.databind.ser.std.MapSerializer <- field com.fasterxml.jackson.databind.ser.AnyGetterWriter._mapSerializer has the type com.fasterxml.jackson.databind.ser.std.MapSerializer <- com.fasterxml.jackson.databind.ser.AnyGetterWriter is used as parameter in method void com.fasterxml.jackson.databind.ser.BeanSerializerBuilder::setAnyGetter(com.fasterxml.jackson.databind.ser.AnyGetterWriter) <- com.fasterxml.jackson.databind.ser.BeanSerializerBuilder is used as parameter in method com.fasterxml.jackson.databind.ser.BeanSerializerBuilder com.fasterxml.jackson.databind.ser.BeanSerializerModifier::updateBuilder(com.fasterxml.jackson.databind.SerializationConfig, com.fasterxml.jackson.databind.BeanDescription, com.fasterxml.jackson.databind.ser.BeanSerializerBuilder) <- com.fasterxml.jackson.databind.ser.BeanSerializerModifier is used as parameter in method com.fasterxml.jackson.databind.ser.SerializerFactory com.fasterxml.jackson.databind.ser.SerializerFactory::withSerializerModifier(com.fasterxml.jackson.databind.ser.BeanSerializerModifier) <- field com.fasterxml.jackson.databind.ObjectWriter._serializerFactory has the type com.fasterxml.jackson.databind.ser.SerializerFactory <- com.fasterxml.jackson.databind.ObjectWriter is returned from method com.fasterxml.jackson.databind.ObjectWriter com.fasterxml.jackson.databind.ObjectMapper::writerWithType(com.fasterxml.jackson.databind.JavaType) <- com.fasterxml.jackson.databind.ObjectMapper is used as parameter in method void org.eclipse.leshan.senml.json.jackson.SenMLJsonJacksonEncoderDecoder::(org.eclipse.leshan.core.util.json.JacksonJsonSerDes<org.eclipse.leshan.senml.SenMLRecord>, com.fasterxml.jackson.databind.ObjectMapper) (method void org.eclipse.leshan.senml.json.jackson.SenMLJsonJacksonEncoderDecoder::(org.eclipse.leshan.core.util.json.JacksonJsonSerDes<org.eclipse.leshan.senml.SenMLRecord>, com.fasterxml.jackson.databind.ObjectMapper) is part of the API)"

Solution ?

I think MyTokenizer should be protected instead of package ?

(issue found with 2.15.3 and also tested with 2.17.1)

@pjfanning
Copy link
Member

Makes sense - if protected JavaType parseType(MyTokenizer tokens, int nestingAllowed) is protected and we allow users to subclass com.fasterxml.jackson.databind.type.TypeParser then MyTokenizer needs to be public or protected. There are a number of other protected methods in TypeParser that take a MyTokenizer instance as input too.

I would prefer if a lot more of jackson-databind was private. Making so many methods protected has consequences. It requires that a lot of other code needs to be public or protected.

In this case, it could be viewed as breaking binary compatibility but I think the MyTokenizer should be made private or left as package private and the API methods that take MyTokenizer inputs could be changed to have StringTokenizer as the param type instead. MyTokenizer extends StringTokenizer.

@cowtowncoder
Copy link
Member

cowtowncoder commented Jul 4, 2024

Ok. Here's my perspective: I think these kinds of items are almost waste of time. I see rather modest benefits from possible changes; moderate chance of regression; and a high chance of bike shedding.

As a result I have no interest in changes for 2.x BUT if others are more interested in making changes, am perfectly fine with changes to upcoming 3.0 (branch master).
So PR(s) against master may be accepted.

EDIT: changed my mind, see below.

@cowtowncoder
Copy link
Member

Ok. So, change of MyTokenizer argument to StringTokenizer won't work due to calls getAllInput() and getRemainingInput().

But I decided I'll change MyTokenizer to be "protected" instead of package-protected, in case that helps scanners avoid reporting issues (and my having to hear about them :) ).
Change goes in 2.18.0; compatibility in this case seems less relevant as it is not part of public api.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants