Set deserializing in Spring Native image problem - jackson-databind

I'm stuck with a problem on a built Spring Native image:
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.http.converter.HttpMessageConversionException: Type definition error: [collection type; class java.util.HashSet, contains [simple type, class java.lang.Object]]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of java.util.HashSet (no Creators, like default constructor, exist): no default no-arguments constructor found
at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 5, column: 14] (through reference chain: com.example.app.payload.request.SignupRequest["roles"])] with root cause
From this description it seems that I need use custom deserializer, but the problem appears only if I run code from native image - same code works perfectly well if run from JAR.
POJOs are very simple:
public class SignupRequest {
#NotBlank
#Size(min = 3, max = 20)
private String username;
#NotBlank
#Size(max = 50)
#Email
private String email;
private Set<String> roles;
#NotBlank
#Size(min = 6, max = 40)
private String password;
// getters & setters no Lombok (but Lombok is in project)
}
Controller uses standard (nothing fancy) annotations:
public ResponseEntity<MessageResponse> registerUser(#Valid #RequestBody SignupRequest signUpRequest)
Has anyone encountered a similar problem?

Finally I found missing part - I have to add HashSet to SerializationHint:
#SpringBootApplication
#SerializationHint(types = {
java.util.HashSet.class
})
public class SpringNativeApplication {
public static void main(String[] args) {
// ...
}
}

Related

Can't inject the guice dependency in the jersey filter

In the process of setup a bridge between guice and jersey, I ran into one problem.
When trying to create a jersey filter, I was unable to inject guice dependencies into it.
I found a duplicate, however there is no solution to the problem there.
Everything is exactly the same.
The only difference is that I don't get a startup error. The filter works, but my dependencies are null.
Interestingly, Filter and HttpFilter work fine. But it doesn't really work for me.
There's another thing that's interesting. In the resource, which I understand is an HK2 dependency, I can inject guice bean.
#ApplicationPath("/test")
private static class TestApplicationConfig extends ResourceConfig
{
public TestApplicationConfig()
{
register(JacksonFeature.class);
register(AuthFilter.class);
register(new ContainerLifecycleListener()
{
public void onStartup(Container container)
{
ServletContainer servletContainer = (ServletContainer) container;
ServiceLocator serviceLocator = container.getApplicationHandler().getServiceLocator();
GuiceBridge.getGuiceBridge().initializeGuiceBridge(serviceLocator);
GuiceIntoHK2Bridge guiceBridge = serviceLocator.getService(GuiceIntoHK2Bridge.class);
Injector injector = (Injector) servletContainer
.getServletContext()
.getAttribute(Injector.class.getName());
guiceBridge.bridgeGuiceInjector(injector);
}
public void onReload(Container container)
{
}
public void onShutdown(Container container)
{
}
});
}
}
In ServletModule child.
serve(path).with(ServletContainer.class, ImmutableMap.of(
"javax.ws.rs.Application", TestApplicationConfig.class.getName(),
"jersey.config.server.provider.packages", sb.toString()));
I trying with register(AuthFilter.class) and #Provider
#Singleton
#Provider
public class AuthFilter implements ContainerRequestFilter
{
#Inject
private SomeInjectedService someInjectedService; **// null here**
#Context
private ResourceInfo resourceInfo;
#Override
public void filter(ContainerRequestContext requestContext) throws IOException
{
// some code
}
}
SomeInjectedService I register by guice
bind(SomeInjectedService.class).asEagerSingleton();
Where can I start diagnosing and what can I do?
UPD:
I noticed different behavior when using different annotations.
If I use javax.inject.Inject, I get the following error message.
org.glassfish.hk2.api.MultiException: A MultiException has 3 exceptions. They are:
1. org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=SomeInjectedService,parent=AuthFilter,qualifiers={},position=-1,optional=false,self=false,unqualified=null,1496814489)
2. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of some.package.AuthFilter errors were found
3. java.lang.IllegalStateException: Unable to perform operation: resolve on some.package.AuthFilter
If com.google.inject.Inject, just null. As I understand this method is not correct.
Considering that javax Inject is trying to inject the service but can't find it. Can we conclude that the bridge is not working correctly? But if it's not working correctly, why can I inject this service into my resource?
#Path("/test")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class SomeResource
{
private final SomeInjectedService someInjectedResource;
#Inject // here I use javax annotation and this code working correctry
public SomeResource(SomeInjectedService someInjectedResource)
{
this.someInjectedResource = someInjectedResource;
}
#GET
#Path("/{user}")
public Response returnSomeResponse(#PathParam("user") String user) throws Exception
{
// some code
}
}

[vaadin]nullPointerExecption when tring to use service in view constructor

I am new to vaadin flow. I am trying to create a list view by following tutorial provided on site.
https://vaadin.com/docs/v14/flow/tutorials/in-depth-course/configuring-vaadin-grid
#Route("")
public class MainView extends VerticalLayout {
private ContactService contactService;
private Grid<Contact> grid = new Grid<>(Contact.class);
public MainView(ContactService contactService) {
this.contactService = contactService;
addClassName("list-view");
setSizeFull();
configureGrid();
add(grid);
updateList();
}
private void configureGrid() {
grid.addClassName("contact-grid");
grid.setSizeFull();
grid.setColumns("firstName", "lastName", "email", "status");
}
private void updateList() {
grid.setItems(contactService.findAll());
}
}
Here when i am executing updateList() method i am getting nullPointerExecption on service instance. I tried using repository.findAll() but facing same issue.
To check the if there is issue in service I created REST API and called the same method in service here i am getting proper result. Please help.
This is the error I am getting.
There was an exception while trying to navigate to '' with the exception message 'Error creating bean with name 'com.example.demo.ui.MainView': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.demo.ui.MainView]: Constructor threw exception; nested exception is java.lang.NullPointerException'
Annotate your ContactService implementation with #Service?

Integrated Swagger and previously working code breaks: cannot deserialize from Object value (no delegate- or property-based Creator

I successfully integrated swagger to several spring boot services.
Had to allow the endpoints to bypass authentication by adding in respective #EnableWebSecurity class that extends WebSecurityConfigurerAdapter (this had worked for other services fine) :
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
#Order(1)
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
...
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.antMatcher("/**")
...
.antMatchers("/actuator/**").permitAll()
.antMatchers("/v2/api-docs", "/configuration/**", "/webjars/**","/swagger*/**") // ADDED THIS for swagger
.permitAll() // ADDED THIS for swagger
.antMatchers("/challenge").permitAll()
.antMatchers("/token").permitAll() // ENDPOINT with complaint now, that was previously ok.
.anyRequest()
.authenticated()
.and()
.cors();
}
...
}
For a specific one, however, once I added the relevant swagger code & dependencies, it seems to have broken and complains on what was working initially.
this is endpoint with the complaint :
#PostMapping("/token")
public ResponseDto token(#Valid #RequestBody TokenRequest request) {
try {
return service.generateJwtFromCode(request.getId(), request.getCode());
}
...
catch (Exception exception) {..
}
}
nested exception is on no constructor found for this class:
#AllArgsConstructor
public class TokenRequest {
#NotEmpty
#JsonProperty
private final String id;
#NotEmpty
#Getter
private final String code;
public UUID getId() {
return UUID.fromString(id);
}
}
Could not resolve parameter [0] in responseDTO Controller.token(Service.TokenRequest): Type definition error: [simple type, class TokenRequest]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `service.TokenRequest` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (PushbackInputStream); line: 1, column: 2]
o.s.web.servlet.DispatcherServlet : Failed to complete request: org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class service.TokenRequest]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `service.TokenRequest` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (PushbackInputStream); line: 1, column: 2]
o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in …
Not sure what it has to do with swagger integration. If i remove swagger integration code, it works fine with the same code, and doesn't complain about the type-conversion failure.
For resolving this, I also took someone's suggestion of
upgrading dependency for com.fasterxml.jackson.core
and rebuilding the code. But still no success.
compileOnly 'com.fasterxml.jackson.core:jackson-databind:2.11.2'
Things I have tried but didn't resolve:
Added a default/empty constructor
(for most others with similar problem it worked by that, for me it complaint thereafter on
error: variable id might not have been initialized
}
Added this to the tokenRequest class:
#Value
#AllArgsConstructor(onConstructor = #__(#JsonCreator(mode = JsonCreator.Mode.PROPERTIES))
Had a different error:
c.j.MappingJackson2HttpMessageConverter : Failed to evaluate Jackson deserialization for type [[simple type, class TokenRequest]]
InvalidDefinitionException: Invalid type definition for type `TokenRequest`: More than one argument (#0 and #1) left as delegating for Creator [constructor for TokenRequest, annotations: {interface com.fasterxml.jackson.annotation.JsonCreator=#com.fasterxml.jackson.annotation.JsonCreator(mode=DELEGATING)}]: only one allowed
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:62)...
Solution was to add a default constructor AND also remove final variables.
#AllArgsConstructor
public class TokenRequest {
#NotEmpty
#JsonProperty
private String id; // code fixed issue
#NotEmpty
#Getter
private String code; // code fixed issue
public TokenRequest(){} // code fixed issue
public UUID getId() {
return UUID.fromString(id);
}
}

Grails 3.x - tests from grails 2.5.x don't work

I have a domain class, which extends non-domain class. When my project was on Grails 2.5.3, the test worked fine.
#Mock(Activity)
class ActivitySpec extends Specification {
def "test"(){
expect:
new Activity(name: 'dfd').save()
}
}
The domain
class Activity extends DomainRestResource {
String name
String code
String description
static hasMany = [....]
static belongsTo = [... ]
static constraints = {
name maxSize: 50
....
}
static mapping = {
table name: 'tt_activity'
}
}
DomainRestResource is defined in src/main/groovy/com/...
DomainRestResource.groovy
abstract class DomainRestResource extends UniversalRestResource {
#Autowired
def connectionManager
#Autowired
def userActivityService
#Autowired
def dataSource
protected transient int limit
protected transient int offset
private transient String tableName
/*
many static methods and fields
and some logic
*/
}
And UniversalRestResource.groovy
abstract class UniversalRestResource {
/*
some logic
*/
abstract List<Object> findObjectsByQuery(String query, int limit, int offset)
/*and any others abstract methods*/
}
Now i'm upgrading the project to Grails 3.1.1 and everything works fine except all my tests.
Test result on grails 3.1.1:
org.grails.datastore.mapping.model.IllegalMappingException: Mapped identifier [id] for class [com.astaprime.rest.DomainRestResource] is not a valid property
at org.grails.datastore.mapping.model.config.GormMappingConfigurationStrategy.getIdentity(GormMappingConfigurationStrategy.java:887)
at org.grails.datastore.mapping.model.AbstractPersistentEntity.resolveIdentifier(AbstractPersistentEntity.java:196)
at org.grails.datastore.mapping.model.AbstractPersistentEntity.initialize(AbstractPersistentEntity.java:117)
at org.grails.datastore.mapping.model.AbstractPersistentEntity.getRootEntity(AbstractPersistentEntity.java:221)
at org.grails.datastore.mapping.model.AbstractMappingContext.initializePersistentEntity(AbstractMappingContext.java:271)
at org.grails.datastore.mapping.model.AbstractMappingContext.initialize(AbstractMappingContext.java:250)
at grails.test.mixin.domain.DomainClassUnitTestMixin.initializeMappingContext(DomainClassUnitTestMixin.groovy:93)
at grails.test.mixin.domain.DomainClassUnitTestMixin.mockDomains(DomainClassUnitTestMixin.groovy:87)
at org.spockframework.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:153)
at org.spockframework.runtime.model.MethodInfo.invoke(MethodInfo.java:84)
at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:88)
at org.spockframework.runtime.extension.builtin.AbstractRuleInterceptor$1.evaluate(AbstractRuleInterceptor.java:37)
at grails.test.runtime.TestRuntimeJunitAdapter$1$2.evaluate(TestRuntimeJunitAdapter.groovy:46)
at org.spockframework.runtime.extension.builtin.TestRuleInterceptor.intercept(TestRuleInterceptor.java:38)
at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:87)
at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:88)
at org.spockframework.runtime.extension.builtin.AbstractRuleInterceptor$1.evaluate(AbstractRuleInterceptor.java:37)
at grails.test.runtime.TestRuntimeJunitAdapter$3$4.evaluate(TestRuntimeJunitAdapter.groovy:73)
at org.spockframework.runtime.extension.builtin.ClassRuleInterceptor.intercept(ClassRuleInterceptor.java:38)
at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:87)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
If remove "extends DomainRestResource" from domain, the test succeeds.
I cannot remove it from all my domain classes, it's very important for program logic.
Haw can i fix this? Thanx!
The solution is just upgrade Grails to version 3.1.2
The issue on Github

Cannot access domain property from Java class (in src folder)

I cannot access exploits property in domain class - Scenario , from my java class - MatchScenario , located in Grails src folder.
Already tried :
Explicit methods :
I have tried explicitly creating the get;set; but I get stackOverflow error since the setExploits() is called infinitely by itself for some reason.
Service to return the exploit field,
Though the service was created, it's never called on my fork-debug integration testing, so tests hangs with no exception
compilation error ->
Error:(59, 44) java: cannot find symbol
symbol: variable exploits
location: variable scenario of type core.Scenario
Java class, error on the inner loop ->
public class MatchScenario implements Callable{
private static final Logger LOG = Logger.getLogger(MatchScenario.class.getCanonicalName());
private List<Scenario> scenarioList
#Override
public List<Scenario> call() throws Exception {
LOG.debug( "*********************** schedule matcher called *****************************" );
if (scenarioList==null) {
LOG.debug("scenarioList not initialized ");
return null;
}
List<Scenario> scenarioAvailable = new ArrayList<Scenario>();
for (Scenario scenario : scenarioList){
for (Exploit exploit : scenario.exploits){
//println 'exploit -> '+exploit
if (!match( exploit.getExpression() ) ){
break;
}
}
//happens only when all scenario are available ( no break issued )
scenarioAvailable.add(scenario);
}
return scenarioAvailable;
}
private boolean match(String expression) {
return true;
}
}
Scenario domain object ->
package core
class Scenario {
String name
static belongsTo = [ Exploit ]
static hasMany = [ exploits : Exploit ]
static constraints = {
name nullable: false , maxSize: 32
}
}
You're confusing fields and properties. When you declare a property in a Groovy class, e.g. String name, the Groovy compiler converts that to a private field and adds a getter and a setter (unless you already defined one or both of them - it won't overwrite), in this case something like
private String name
public void setName(String name) { this.name = name }
public String getName() { return name }
It only does this if there's no scope modifier, so public String name and protected String name would both stay as defined.
One benefit of this is that you can later add logic to the getter and/or setter to modify the value, do some validation checks or computations, etc., and in Groovy you would still read and write to the name property since property access always calls the underlying setters and getters, and since properties like this are a Groovy-only thing that Java can't access, you would have been calling the setter and getter from Java all along, so you wouldn't need to recompile the Java classes that used the class.
Declaring a hasMany like yours creates an exploits property, effectively
Set<Exploit> exploits
and that property (added by a Grails AST transformation) is likewise converted to a private field with a getter and setter. So to get this working from Java, use the getter:
for (Exploit exploit : scenario.getExploits()) {

Resources