Amber Akkermans
Amber Akkermans

Reputation: 75

java.lang.NoSuchMethodError: java.time.Instant.<init>()

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

Answers (1)

rzwitserloot
rzwitserloot

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

Related Questions