Reputation: 75
I get the error java.lang.NoSuchMethodError: java.time.Instant.<init>()
when in a rest-API documentation (swagger) I try to do a post request with as body the following json:
{
"accountId": "string",
"name": "string",
"value": "string",
"expires": 0
}
this maps to the model:
AccountClientIdentifierEntity{
accountId string
name string
value string
expires integer($int64)
}
Now in my Java code this expires attribute is actually an Instant, but it somehow gets parsed as an Integer here, so I guess my problem lies here, when I post with the "0" instead of an Instant. Can someone help me to fix this, or at least catch the error correctly?
Full code: Entity:
/**
* The Class UserEntity.
*/
@XmlRootElement(name = "accountClientIdentifier")
@XmlType(propOrder = { "accountId", "name", "value", "expires"})
@JsonInclude(JsonInclude.Include.NON_NULL)
public class AccountClientIdentifierEntity {
public static void registerToContextProvider(){
try {
CustomContextProvider.registerClass(com.inteno.iopsys.plugin.restapi.entity.AccountClientIdentifierEntity.class);
} catch (Exception e){
Log.error("Could not register AccountClientIdentifierEntity: "+e.getMessage());
}
}
/** The username. */
private String accountId;
/** The name. */
private String name;
/** The value. */
private String value;
/** expires. */
private Instant expires;
/**
* Instantiates a new user entity.
*/
public AccountClientIdentifierEntity() {
}
/**
* Instantiates a new user entity.
*
* @param accountId
* the account ID
* @param name
* the name
* @param value
* the value
*/
public AccountClientIdentifierEntity(String accountId, String name, String value) {
this.accountId = accountId;
this.name = name;
this.value = value;
}
service path:
@POST
@Path("/identifiers")
@ApiOperation(value = "Add a new account client identifier")
@ApiResponses(value = {@ApiResponse(code = 201, message = "Created")})
public Response createAccountClientId(
@ApiParam(value = "The new identifier to create", required = true) AccountClientIdentifierEntity accountClientIdentifierEntity
) throws ServiceException {
controller.createOrUpdateAccountClientIdentifier(accountClientIdentifierEntity);
return Response.status(Response.Status.CREATED).build();
}
Stacktrace:
2023.01.05 09:25:21 WARN [Jetty-QTP-API-1-821]: HttpChannel.java:700 - /restapi/v1/account/identifiers
java.lang.NoSuchMethodError: java.time.Instant.<init>()
at com.sun.xml.bind.v2.ClassFactory.tryGetDeclaredConstructor(ClassFactory.java:115) ~[jaxb-runtime-2.3.2.jar:2.3.2]
at com.sun.xml.bind.v2.ClassFactory.create0(ClassFactory.java:76) ~[jaxb-runtime-2.3.2.jar:2.3.2]
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.createInstance(ClassBeanInfoImpl.java:255) ~[jaxb-runtime-2.3.2.jar:2.3.2]
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.createInstance(UnmarshallingContext.java:672) ~[jaxb-runtime-2.3.2.jar:2.3.2]
at com.sun.xml.bind.v2.runtime.unmarshaller.StructureLoader.startElement(StructureLoader.java:158) ~[jaxb-runtime-2.3.2.jar:2.3.2]
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:547) ~[jaxb-runtime-2.3.2.jar:2.3.2]
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:526) ~[jaxb-runtime-2.3.2.jar:2.3.2]
at com.sun.xml.bind.v2.runtime.unmarshaller.InterningXmlVisitor.startElement(InterningXmlVisitor.java:45) ~[jaxb-runtime-2.3.2.jar:2.3.2]
at com.sun.xml.bind.v2.runtime.unmarshaller.StAXStreamConnector.handleStartElement(StAXStreamConnector.java:216) ~[jaxb-runtime-2.3.2.jar:2.3.2]
at com.sun.xml.bind.v2.runtime.unmarshaller.StAXStreamConnector.bridge(StAXStreamConnector.java:150) ~[jaxb-runtime-2.3.2.jar:2.3.2]
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:385) ~[jaxb-runtime-2.3.2.jar:2.3.2]
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:364) ~[jaxb-runtime-2.3.2.jar:2.3.2]
at com.sun.jersey.json.impl.BaseJSONUnmarshaller.unmarshalJAXBElementFromJSON(BaseJSONUnmarshaller.java:111) ~[?:?]
at com.sun.jersey.json.impl.BaseJSONUnmarshaller.unmarshalFromJSON(BaseJSONUnmarshaller.java:100) ~[?:?]
at com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider.readFrom(JSONRootElementProvider.java:154) ~[?:?]
at com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.readFrom(AbstractRootElementProvider.java:111) ~[?:?]
at com.sun.jersey.spi.container.ContainerRequest.getEntity(ContainerRequest.java:490) ~[?:?]
at com.sun.jersey.server.impl.model.method.dispatch.EntityParamDispatchProvider$EntityInjectable.getValue(EntityParamDispatchProvider.java:123) ~[?:?]
at com.sun.jersey.server.impl.inject.InjectableValuesProvider.getInjectableValues(InjectableValuesProvider.java:86) ~[?:?]
at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$EntityParamInInvoker.getParams(AbstractResourceMethodDispatchProvider.java:153) ~[?:?]
at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$ResponseOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:203) ~[?:?]
at com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:75) ~[?:?]
at com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:302) ~[?:?]
at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147) ~[?:?]
at com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:108) ~[?:?]
at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147) ~[?:?]
at com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:84) ~[?:?]
at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1542) ~[?:?] at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1473) ~[?:?] at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1419) ~[?:?]
at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1409) ~[?:?]
at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:409) ~[?:?]
at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:558) ~[?:?]
at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:733) ~[?:?]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:590) ~[jetty-servlet-api-4.0.6.jar:?]
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:764) ~[jetty-servlet-10.0.5.jar:10.0.5]
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:508) ~[jetty-servlet-10.0.5.jar:10.0.5] at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:221) ~[jetty-server-10.0.5.jar:10.0.5]
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1373) ~[jetty-server-10.0.5.jar:10.0.5]
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:176) ~[jetty-server-10.0.5.jar:10.0.5]
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:463) ~[jetty-servlet-10.0.5.jar:10.0.5]
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:174) ~[jetty-server-10.0.5.jar:10.0.5]
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1295) ~[jetty-server-10.0.5.jar:10.0.5]
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:129) ~[jetty-server-10.0.5.jar:10.0.5]
at org.eclipse.jetty.server.handler.HandlerList.handle(HandlerList.java:51) ~[jetty-server-10.0.5.jar:10.0.5]
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122) ~[jetty-server-10.0.5.jar:10.0.5]
at org.eclipse.jetty.server.Server.handle(Server.java:562) ~[jetty-server-10.0.5.jar:10.0.5]
at org.eclipse.jetty.server.HttpChannel.lambda$handle$0(HttpChannel.java:399) ~[jetty-server-10.0.5.jar:10.0.5]
at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:656) ~[jetty-server-10.0.5.jar:10.0.5]
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:391) [jetty-server-10.0.5.jar:10.0.5]
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:282) [jetty-server-10.0.5.jar:10.0.5]
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:319) [jetty-io-10.0.5.jar:10.0.5]
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:100) [jetty-io-10.0.5.jar:10.0.5]
at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.onFillable(SslConnection.java:538) [jetty-io-10.0.5.jar:10.0.5]
at org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:387) [jetty-io-10.0.5.jar:10.0.5]
at org.eclipse.jetty.io.ssl.SslConnection$2.succeeded(SslConnection.java:161) [jetty-io-10.0.5.jar:10.0.5]
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:100) [jetty-io-10.0.5.jar:10.0.5]
at org.eclipse.jetty.io.SocketChannelEndPoint$1.run(SocketChannelEndPoint.java:101) [jetty-io-10.0.5.jar:10.0.5] at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:333) [jetty-util-10.0.5.jar:10.0.5]
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:310) [jetty-util-10.0.5.jar:10.0.5]
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168) [jetty-util-10.0.5.jar:10.0.5]
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:126) [jetty-util-10.0.5.jar:10.0.5]
at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:378) [jetty-util-10.0.5.jar:10.0.5]
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:894) [jetty-util-10.0.5.jar:10.0.5]
at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1038) [jetty-util-10.0.5.jar:10.0.5]
at java.lang.Thread.run(Thread.java:834) [?:?]
Caused by: java.lang.NoSuchMethodException: java.time.Instant.<init>()
at java.lang.Class.getConstructor0(Class.java:3350) ~[?:?]
at java.lang.Class.getDeclaredConstructor(Class.java:2554) ~[?:?]
at com.sun.xml.bind.v2.ClassFactory.tryGetDeclaredConstructor(ClassFactory.java:107) ~[jaxb-runtime-2.3.2.jar:2.3.2]
... 65 more
Upvotes: 3
Views: 2178
Reputation: 103254
You're asking JAXB to put the peg (a number value received from the JSON and identifier by swagger as $int64) in the hole (the Instant expires;
field in your AccountClientIdentifierEntity
class).
Turns out, that's a square peg and a round hole. JAXB tries its best, and given that it has no idea what an Instant
might be, is planning to construct one and perhaps find a set method maybe. That's not how Instant
works, however; you're looking specifically for Instant.ofEpochSecond
or ofEpochMilli
, and we are now truly getting into the root issue here: What does that $int64 even mean? Is it seconds since 1970? milliseconds? Nanofurlongs? Perhaps it's days since 1902, using the decimal fraction for hours and seconds?
Asking JAXB to just take a flying wild stab at it seems unreasonable, and indeed, isn't a thing JAXB can do, nor will it ever. You must tell it what to do.
To do this, you tell JAXB that there is a specific unmarshaller available for that field.
An @XmlJavaTypeAdapter
annotation should be able to do the job; you can annotate the expires
field with it, passing a class reference to a class that implements XmlAdapter
.
The jaxb-java-time-adapters
project could be useful here; possibly only to look at the source to know what to do.
Upvotes: 5