简体   繁体   中英

why Glassfish server throws NoSuchMethodError when creating an instance of java.time.LocalDate with ZoneId

I have this code that creates an instance of java.time.LocalDate. I compiled it with JDK 14 and it runs without any error:

public void foo(Date d){
  LocalDate d1 = LocalDate.ofInstant(d.toInstant(), ZoneId.systemDefault());
  System.out.println("Created LocalDate from Date: "+d1);
}

When I try to do the same thing inside a backing bean for a JSF page running on Glassfish server 5.1, it throws a NoSuchMethodError.

public void validateDateTimeLine(FacesContext fc, UIComponent ui, Object value) {
        Date then = (Date) value;
        try {
            LocalDate dthen = LocalDate.ofInstant(then.toInstant(), ZoneId.systemDefault());
            LocalDate now = LocalDate.ofInstant(Instant.now(), ZoneId.systemDefault());
            ....................................
        } catch (Exception | NoSuchMethodError e) {
            
        }
}

The stack trace:

java.lang.NoSuchMethodError: java.time.LocalDate.ofInstant(Ljava/time/Instant;Ljava/time/ZoneId;)Ljava/time/LocalDate;
    at org.me.mavenlistservicedb.bean.LoginManagment.validateDateTimeLine(LoginManagment.java:176)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.sun.el.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:181)
    at com.sun.el.parser.AstValue.invoke(AstValue.java:289)
    at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:304)
    at org.jboss.weld.module.web.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40)
    at org.jboss.weld.module.web.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)
    at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:107)
    at javax.faces.validator.MethodExpressionValidator.validate(MethodExpressionValidator.java:109)
    at javax.faces.component.UIInput.validateValue(UIInput.java:1248)
    at javax.faces.component.UIInput.validate(UIInput.java:1037)
    at javax.faces.component.UIInput.executeValidate(UIInput.java:1334)
    at javax.faces.component.UIInput.processValidators(UIInput.java:757)
    at javax.faces.component.UIData.iterate(UIData.java:2150)
    at javax.faces.component.UIData.processValidators(UIData.java:1273)
    at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1298)
    at javax.faces.component.UIForm.processValidators(UIForm.java:269)
    at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1298)
    at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1332)
    at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:77)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:201)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:670)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1540)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:217)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:119)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:611)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:550)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:114)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:332)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:199)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:463)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:168)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:206)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:180)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:242)
    at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:539)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:593)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:573)
    at java.lang.Thread.run(Thread.java:748)

Any idea?

Thanks

While the LocalDate.ofInstant method exists in Java 14, it does not in the LocalDate class from Java 8. I'm expecting that you are compiling using JDK 14, but running it on a lower version of Java.

If you read the documentation, ie the javadoc of LocalDate.ofInstant(Instant, ZoneId) , you will find:

Since:

9

The code was compiled against a Java 9+ Runtime Library, but was compiled with -target 1.8 and you're running with Java 8.

Don't do that, ie always make sure that you're compiling against the same version of the Runtime Library as the version of the generated bytecode.

Solution: Use compiler option --release 8 instead of -source 8 -target 8 . That option was specifically added to the Java 9+ compiler to make it easier to compile for older versions of Java against the correct version of the Runtime Library.

Recommended: See JEP 247: Compile for Older Platform Versions for more detail.


UPDATE

It is mentioned in comments to aran's answer that NetBeans is used to compile the code. I don't have NetBeans, but I believe it functions very similar to the Eclipse I use, so I'll show how to fix this in Eclipse, and hope you can apply it yourself to NetBeans.

In Eclipse, you need to specify the target Java version in 2 places:

  • The classpath (or buildpath in Eclipse):

    在此处输入图像描述

  • The compiler compliance level ( -source and -target on command-line):

    在此处输入图像描述

In the olden days, those two should always refer to the same version, eg as shown here, where the build path refers to where JDK 15 is installed, and the compliance level is set to 15 .

Starting with Java 9 and the new --release compiler option, you can target older versions of Java, without the need to have such an older version installed.

Leaving the build path pointing to JDK 15, you can change the compliance version to eg 8, if you also check the Use '--release' option checkbox (circled in blue).

It is very important to check the Use '--release' option checkbox if you don't change the build path to match the compliance version.

Doing this will ensure that the compiler fails on the LocalDate.ofInstant() call, because that method didn't exist in JDK 8, even though you still have JDK 15 on the build path.

According to the Java8 and further version regarding LocalDate and LocalDateTime , there were some changes from the one GlassFish uses (jre8) and the next ones, starting from Java9.

  • Java8
    ofInstant is implemented on LocalDateTime

  • Java9+

    ofInstant is implemented on LocalDate .

In order to follow your logic, you could do this:

LocalDateTime dTime = LocalDateTime.ofInstant(then.toInstant(),ZoneId.systemDefault());
LocalDate dthen = dTime.toLocalDate();

LocalDateTime 's toLocalDate() would allow you get the appropiate variable type: LocalDate

public LocalDate toLocalDate()

Gets the LocalDate part of this date-time. This returns a LocalDate with the same year, month and day as this date-time.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM