My IDE is not recognizing HTML commands for my servlet [duplicate] - java

This question already has answers here:
How do I import the javax.servlet / jakarta.servlet API in my Eclipse project?
(16 answers)
Closed 1 year ago.
I am learning how to create a servlet that takes HTML code and makes a program in my browser.
This code was supposed to output a simple welcome message in my browser via HTML. However, My eclipse IDE does not recognize any of the HTML commands in this code. It says that the imports are not accessible and that the HTTP variables can't be resolved to a type. I'm using tomcat version 10.0.12 and Java 13 for the code (I also have java 16 but eclipse only gave me the option to use 13). I've tried uninstalling and reinstalling Tomcat several times and adding servlet-api.jar but none of those changed a thing. I know there's an extra step I'm missing but I can't figure out what it is?
import jakarta.servlet.*;
import jakarta.servlet.http.*;
import java.io.*;
public class WelcomeServlet extends HttpServlet {
#Override
protected void doGet( HttpServletRequest request,
HttpServletResponse response ) throws ServletException, IOException {
response.setContentType( "text/html" );
PrintWriter out = response.getWriter();
out.println( "<title>Welcome to Servlets!</title>" );
{...}
out.println( "</html>" );
out.close(); // close stream to complete the page
}
}

You've messed up your imports. It sounds like you're following a tutorial that's 20+ years old, a lot of what you're doing is extremely outdated. The web is a fairly fast moving environment; I strenously advise against using such old tutorials.
The correct import is import javax.servlet.http.HttpServletRequest;.
Some notes on what you're doing that are bad ideas:
Star imports aren't advised; it's a bit too easy to get confused about where things live or which type(s) you are fetching from where. Your IDE manages your imports for you; let it.
You don't want to write HTML inside strings inside your code. Use a templating engine such as Freemarker, Velocity, Thymeleaf, or Google Closure Templates. Alternatively, write static HTML with a ton of javascript (probably with a client-side javascript-based framework) and write your server as an API that doesn't 'answer' in terms of HTML files; it answers in terms of some structured data format such as JSON. Your static (as in, unchanging; any file-serving HTTP service can provide them) HTML+CSS+Javascript does the job of calling your API to get this structured data, and then your HTML+CSS+JavaScript does the job of rendering it into HTML.
Raw servlets is outdated; the API is extremely old and it shows, for example, you can't even use a simple for-each loop to iterate over all parameter names, because the API returns the obsolete Enumeration instead of the more modern Iterator or even Stream. You neither get the benefit of storing intermediate state in fields (because you aren't guaranteed one instance per invocation), but you also don't get to just dump it all in static fields either (as the spec doesn't guarantee that there'll only ever be one instance) - the worst of both worlds. Look into JAX-RS, Jersey, Dropwizard, sparkjava, or other such frameworks.

tl;dr
Your project lacks a JAR containing the definition of the Jakarta Servlet API (a set of interfaces).
Add jakarta.servlet-api as a dependency to your project, to present to your IDE the needed JAR file during development but omitted from your final build’s WAR file.
Details
Your import statements refer to the Jakarta Servlet API. That API is not built into Java. So you must make a Servlet API JAR file available to your IDE while developing.
Typically in Java development we use a tool such as Maven or Gradle to assist our IDE in obtaining external dependencies such as the Servlet API JAR.
If you are using Maven, edit your POM file to specify a dependency for the Servlet API JAR published as part of the Jakarta.ee project, by the Eclipse Foundation.
<!-- https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>5.0.0</version>
<scope>provided</scope>
</dependency>
Notice the scope element, with a value of provided. This means the JAR file should be downloaded, made available to your IDE while developing, but should not be copied into your resulting product when you build.
The output of your build will typically be a WAR file (not JAR). The provided scope means we do not want a copy of the Servlet API JAR within that WAR. The reason is that when developing Jakarta EE web apps, we expect to deploy to a compliant application server that carries its own copy of the Servlet API. Every “profile” of Jakarta EE compliant servers are required to include an implementation of the Servlet API.
So your POM will look something like this:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns = "http://maven.apache.org/POM/4.0.0"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>work.basil.example</groupId>
<artifactId>demo</artifactId>
<version>1.0-SNAPSHOT</version>
<name>demo</name>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>5.0.0</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.2</version>
</plugin>
</plugins>
</build>
</project>
And here is the source code for a simple servlet.
package work.basil.example.demo;
import java.io.*;
import jakarta.servlet.http.*;
import jakarta.servlet.annotation.*;
#WebServlet ( name = "helloServlet", value = "/hello-servlet" )
public class HelloServlet extends HttpServlet
{
private String message;
public void init ( )
{
message = "Hello World!";
}
public void doGet ( HttpServletRequest request , HttpServletResponse response ) throws IOException
{
response.setContentType( "text/html" );
// Hello
PrintWriter out = response.getWriter();
out.println( "<html><body>" );
out.println( "<h1>" + message + "</h1>" );
out.println( "</body></html>" );
}
public void destroy ( )
{
}
}
You said:
I've tried uninstalling and reinstalling Tomcat several times
Completely unrelated to your problem, I expect.
The installation of Tomcat comes with an implementation of the Servlet API. But your IDE does not “see” Tomcat during development. Your IDE needs to see the interfaces defined in the Servlet API.
Your IDE does not actually execute your servlet, so it does not need an implementation, it needs only the interfaces. When you run your Servlet from the IDE, Tomcat is invoked externally from the IDE. The IDE attaches a debugger connection to Tomcat to facilitate interactive debugging, but the IDE and Tomcat are actually running as separate distinct processes on the host OS. And as I said, Tomcat comes bundled with its own implementation of those interfaces, so your servlet is able to execute.
You said you are using Java 13. Be aware that Java 13 is no longer supported. You should move to either the latest version of Java (17, as of 2021-11), or to one of the Long-Term Support (LTS) versions (8, 11, 17).
If using Java 11 or 17 rather than 8, I would suggest using Tomcat 10.1.x rather than Tomcat 10.0.x. Tomcat 10.1.x supports Jakarta EE 9.1 and 10, which supports Java 11 and later versus Java 8.
See the Tomcat version comparison page.

Related

How to exclude packages in Maven that uses the same attribute?

So, I am working with webservices using SOAP and Maven. This error - I think - is a warning instead because it let me run the application and the service just fine for now. Whenever I call any other package inside this module class it turns red. If I don't add packages the error disappears but I need jasperreports (strange, as the involved package got nothing to do with this)
I've followed this: Module reads package from both
Using the solution "implementation and excludes" does nothing. Probably because it is Gradle but I had to try restricting the xml transform using the suggested message.
I also tried Package 'com.example' reads package 'javafx.beans' from both 'javafx.base' and 'javafx.base' this.
I followed this guide as well. https://maven.apache.org/guides/mini/guide-multiple-modules.html
<dependency>
<groupId>sample.ProjectA</groupId>
<artifactId>Project-A</artifactId>
<version>1.0</version>
<scope>compile</scope>
<optional>true</optional> <!-- value will be true or false only -->
</dependency>
Making those package use optional does not help either.
Important note, using a different package I want to use the ERROR WILL CHANGE. I removed and added some so you can withness it. Check these:
In short, a Web Service dependency using some of the declared in the client as well. As mentioned, I went one by one until I found it.
Also, updating javax.xml version of the dependency was a necessary step in order to solve the problem.

Change CodeStar Spring MVC project to Spring Boot

I have a Spring Boot project that works perfectly when run in IDE. I would like to run this via AWS CodeStar. Unfortunately, the default Spring template created by CodeStar uses Spring MVC.
I cannot just overwrite the default Spring MVC project with my Spring Boot project (it doesn't work). I can copy some of my resources to the MVC project, for example index.html and that works. But then features like Thymeleaf don't work. For this and other reasons, I would like to change the provided Spring MVC into the Spring Boot structure I already have.
I followed the instructions here: https://www.baeldung.com/spring-boot-migration
Unfortunately, this doesn't help. I can create Application Entry Point and add Spring Boot dependencies without the app breaking. But when I remove the default dependencies or the configuration associated with the MVC, the app breaks. When trying to reach the URL, I get a 404 error with description:
The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.
Debugging this error message (e.g. https://www.codejava.net/java-ee/servlet/solved-tomcat-error-http-status-404-not-found) didn't help.
The message seems like it's connected to the web resource. I have my web resources in folder resources as well as webapp/resources. And Spring Boot doesn't need any location configuration, right? It uses this location by default.
Can somebody tell me what things to remove and what to add to be able to use my existing Spring Boot project?
EDIT:
This is a link to a default template for AWS CodeStar Spring web application: https://github.com/JanHorcicka/AWS-codestar-template
And this is my Spring Boot project structure:
I realize that you indicated that previously you tried to use your Spring Boot project with some modifications without success, but I think it could be actually a possibility to successfully deploy your application on AWS CodeStar, and it will be my advice.
I also realized that in your screenshot you included several of the required artifacts and classes, but please, double check that you followed these steps when you deployed your application to AWS CodeStar.
Let's start with a pristine version of your Spring Boot project running locally, without any modification, and then, perform the following changes.
First, as indicated in the GitHub link you shared, be sure that you include the following files in your project. They are required for the deployment infrastructure of AWS:
appspec.yml
buildspec.yml
template.yml
template-configuration.json
The whole scripts directory
Please, adapt any necessary configuration to your specific needs, especially, template-configuration.json.
Then, perform the following modifications in your pom.xml. Some of them are required for Spring Boot to work as a traditional deployment and others are required by the deployment in AWS CodeStar.
Be sure that you indicate packaging as war:
<packaging>war</packaging>
To ensure that the embedded servlet container does not interfere with the Tomcat to which the war file is deployed, either mark the Tomcat dependency as being provided as suggested in the above-mentioned documentation:
<dependencies>
<!-- … -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<!-- … -->
</dependencies>
Or exclude the Tomcat dependency in your pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
If necessary, apply this exclusion using some kind of profile that allows you to boot Spring Boot locally and in an external servlet container at the same time.
Next, parameterize the maven war plugin to conform to the AWS CodeStar deployment needs:
<build>
<pluginManagement>
<plugins>
<!-- ... -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<warSourceDirectory>src/main/webapp</warSourceDirectory>
<warName>ROOT</warName>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<!-- ... -->
<plugins>
</pluginManagement>
</build>
I do not consider it necessary, but just to avoid any kind of problem, adjust the name of your final build:
<finalName>ROOT</finalName>
Lastly, as also indicated in the Spring documentation, be sure that your MyProjectApplication - I assume this class is your main entry point subclass SpringBootServletInitializer and override the configure accordingly, something like:
#SpringBootApplication
public class MyProjectApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(MyProjectApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(MyProjectApplication.class, args);
}
}
Please, feel free to adapt the class to your specific use case.
With this setup, try to deploy your application and see if it works: perhaps you can find some kind of library dependencies problem, but I think for the most part it should work fine.
At a first step, you can try to deploy locally the version of the application you will later deploy to AWS CodeStar following the instructions you provided in your project template, basically, once configured with the necessary changes described in the answer, by running:
mvn clean package
And deploying the generated war on your local tomcat environment. Please, be aware that probably the ROOT application already exists in a standard tomcat installation (you can verify it by inspecting the webapps folder): you can override that war file.
For local testing you can even choose a different application name (configuring build.finalName and the warName in your pom.xml file): the important thing is verify if locally the application runs successfully.
If you prefer to, you can choose to deploy the app directly to AWS CodeStar and inspect the logs later it necessary.
In any case, please, pay attention on two things: on one hand, if you have any absolute path configured in your application, it can be the cause of the 404 issue you mention in the comments. Be aware that your application will be deployed in Tomcat with context root '/'.
On the other hand, review how you configured your database access.
Probably you used application.properties and it is fine, but please, be aware that when employing the application the database must be reachable: perhaps Spring is unable to create the necessary datasources, and the persistence manager or related stuff associated with and, as a consequence, the application is not starting. Again, it may be the reason of the 404 error code.
To simplify database connectivity, for testing, at first glance, I recommend you to use simple properties for configuring your datasource, namely the driver class, connection string, username and password. If that setup works properly, you can later enable JNDI or what deemed necessary.
Remember that if you need to change your context name and/or define a datasource pool in Tomcat you can place a context.xml file under a META-INF directory in your web app root path.
This context.xml should look like something similar to:
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/">
<Resource name="jdbc/myDS"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
url="jdbc:mysql://localhost:3306/myds"
driverClassName="com.mysql.jdbc.Driver"
username="root"
password="secret"
/>
</Context>

Issues with WAS Liberty classloader

I have an issue with the WAS Liberty classloader, nothing I do seem to fix it. The issue seems to be with log4j2, which I am using.
I'm running 16.0.0.4 (just upgraded from 8.5.5.9 where this issue also exist). I'm trying to create a webapp using Primefaces 6.0 which connects to Elasticsearch 5.1.1.
I have added the following dependency to maven:
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>${library.elasticsearch.version}</version>
</dependency>
Somewhere along the road I need to do the following:
TransportClient client = new PreBuiltTransportClient(settings)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(HOST), PORT));
Debugging this line hits the following method call in Elasticsearch (class: org.elasticsearch.threadpool.ThreadPool line 203):
logger.debug("created thread pool: {}", entry.getValue().formatInfo(executorHolder.info));
This throws an java.lang.NoSuchMethodError:
org/apache/logging/log4j/Logger.debug(java/lang/String;java/lang/Object;)
Normally we use log4j 2.2, but I have included log4j2 2.7 as described here (Elasticsearch v5.0 uses 2.6.2, v5.1 uses 2.7): https://discuss.elastic.co/t/issue-with-elastic-search-5-0-0-noclassdeffounderror-org-apache-logging-log4j-logger/64262/2
I have also tried to make it "provided". I'm currently building a war file, but I also tried to do it as an ear, same result.
I came accoss this issue on the Elasticsearch 5-alpha: https://github.com/elastic/elasticsearch/issues/19415 Here they note that they wanted to create a server and therefore did not see log4j2 as a consern, but they suggest that you use the REST API instead (although, at the time of writing, this was not usable for Java developers).
So the question is, what do I do? Should I use the REST API (e.g. Jest (https://github.com/searchbox-io/Jest/tree/master/jest)) or ?...
The code I have works fine when running standalone outside Liberty.
UPDATE:
It seems like parts of Liberty does contain log4j v2.2:
class load: org.apache.logging.log4j.core.appender.routing.Route from: file:/C:/deploy/liberty/workarea/org.eclipse.osgi/60/data/cache/com.ibm.ws.app.manager_0/.cache/lib/log4j-core-2.2.jar
...
It loads a lot of classes from this jar, but not the one that I'm having trouble with - this is loaded from an app we have. I tried to bump the version inside our own app, but same issue.

How to write Jersey Multipart webapp, Tomcat Server

I've been doing a lot of REST tutorials and enjoying them. Recently, I tried writing a jersey multipart webapp with Netbeans but I can't seem to because it seems something's missing my jersey library.
I downloaded the jersey-multipart.jar file, but still that didn't help:
#Path("/file")
public class UploadFileService {
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(
#FormDataParam("file") InputStream uploadedInputStream,
#FormDataParam("file") FormDataContentDisposition fileDetail) {
This code is from blog. I'm trying to put it in my webapp, but the #FormDataParam tag and the FormDataContentDisposition class are not recognised. I downloaded the jersey-multipart.jar and that seemed to solve the #FormDataParam tag problem, but not the FormDataContentDisposition class.
I'm using Tomcat 7.0.
How do I go about successfully creating a jersey multipart webapp without any problems? And how come the jersey-multipart jar file isn't included in the jersey library in Netbeans?
Thanks.
Lutz Horn has a point, but for the sake of those using Netbeans 7.4 (Java EE 6) and are still struggling with this issue, here's a step by step on how to create your very own multipart rest web service and deploying on Tomcat, with Netbeans. (Note, deploying on Glassfish requires a slightly different configuration which isn't covered in this answer).
First off, my suggestion is to create a maven web application and not a normal web application. Reason is, the JAX-RS and Jersey libraries that come with Java EE 6 are not sufficient enough, and once you start fiddling around with external jars, things tend to get messy, especially with Jersey. (Hopefully, this has been corrected in Netbeans 8.0 (Java EE 7)).
(1) Create a maven web-app, choose Java EE 6 and Tomcat 7. Once you're done, you'll notice you don't have a web.xml. Most multipart tutorials will tell you to include certain configurations in your web.xml file. Don't bother with that. You don't need a web.xml file.
(2) Create a RESTfull web service by either writing it manually or using the wizard (right click on your maven web-app -- New -- Other -- Web Services -- [choose the RESTful web service you want])
(3) Open your pom.xml (you can find it under the Project Files folder in your maven web-app) and add these dependencies:
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>2.7</version>
</dependency>
If you're doing this for the first time, you need an active internet connection, as maven will download the dependencies from its central repository.
(4) Go to your ApplicationConfig class or whatever class that holds that contains your #ApplicationPath(). It should look like this:
#javax.ws.rs.ApplicationPath("webresources")
public class ApplicationConfig extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new java.util.HashSet<Class<?>>();
resources.add(MultiPartFeature.class);
addRestResourceClasses(resources);
return resources;
}
/**
* Do not modify addRestResourceClasses() method.
* It is automatically populated with
* all resources defined in the project.
* If required, comment out calling this method in getClasses().
*/
private void addRestResourceClasses(Set<Class<?>> resources) {
resources.add(com.mycompany.mavenrestuploader.UploaderResource.class);
}
Note: resources.add(MultiPartFeature.class); That has to be included, otherwise Jersey multipart won't work.
The reason I put that line of code in the getClasses method and not the addRestResourceClasses method is because the addRestResourceClasses method gets modified whenever there's a change to your resource class, and if you include the MultiPartFeature code in there, it will get erased.
Once you've done all these things, you are good to go.
If you're just looking to create a RESTful web service without multipart, follow steps 1 to 3, but in step 3 do not include the jersey-media-multipart dependency.
I hope this helps you ;)
The imports for these two are
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
If you use Maven, add this dependencies:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>2.0</version>
<type>jar</type>
</dependency>
Together with jersey-media-multipart dependency, instead of Application (see below) you can configure ResourceConfig:
#ApplicationPath("/")
public class AppConfig extends ResourceConfig {
public AppConfig() {
packages("packages.to.scan");
register(MultiPartFeature.class);
}
}
or Jersey REST configuration in web.xml:
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
</init-param>

Java 8 Lambda Expression Within REST Service not working

If I put a Java 8 Lambda expression in a REST service, it crashes. If I remove the lambda expression, it works. It does not matter if I use the lambda expression or not. Just the existence the lambda is enough to crash. Everything else Java 8 related seems to work.
Below is my code (simplified):
#Path("finance")
public class FinanceRest {
#GET
#Produces("text/plain")
public String speak() {
return "Hello world.";
}
private void lambdaFunction(Predicate<Account> predicate) {
// Any lambda will cause problems, no matter how simple
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
Stream<Integer> onlyOdds = numbers.stream().filter(n -> n%2 != 0);
}
}
As you can see from the code above, just the existence of a lambda expression will cause failure. As soon as I remove the lambda, it works fine. The other Java 8 stuff is fine (for example, the "Predicate" input parameter).
The error message I'm getting is:
java.lang.ArrayIndexOutOfBoundsException: 25980
I've tried this on Tomcat 7 and 8 using Java 8.
I'm using the standard jax-rs stuff from JavaEE 6.... in other words my POM file has this:
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>6.0</version>
<scope>provided</scope>
</dependency>
Any help would be appreciated.
Thanks.
The exact error message (on Glassfish 4.0... I've tried both Tomcat and Glassfish) is:
java.lang.ArrayIndexOutOfBoundsException: 52264 at
org.objectweb.asm.ClassReader.readClass(ClassReader.java:2015) at
org.objectweb.asm.ClassReader.accept(ClassReader.java:469) at
org.objectweb.asm.ClassReader.accept(ClassReader.java:425) at
org.glassfish.hk2.classmodel.reflect.Parser$5.on(Parser.java:362) at
com.sun.enterprise.v3.server.ReadableArchiveScannerAdapter.handleEntry(ReadableArchiveScannerAdapter.java:165)
at
com.sun.enterprise.v3.server.ReadableArchiveScannerAdapter.onSelectedEntries(ReadableArchiveScannerAdapter.java:127)
at org.glassfish.hk2.classmodel.reflect.Parser.doJob(Parser.java:347)
at
org.glassfish.hk2.classmodel.reflect.Parser.access$300(Parser.java:67)
at
org.glassfish.hk2.classmodel.reflect.Parser$3.call(Parser.java:306)
at
org.glassfish.hk2.classmodel.reflect.Parser$3.call(Parser.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:266) at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:744)
I found the solution!
I was using Jersey 1.17.1. When I upgraded to 2.7 it worked. My pom file had the following:
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-bundle</artifactId>
<version>1.17.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
<version>1.17.1</version>
<scope>compile</scope>
</dependency>
I removed those and added:
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.7</version>
</dependency>
And of course I had to modify the web.xml file to have:
<servlet>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
</servlet>
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/rs/*</url-pattern>
</servlet-mapping>
Now everything is working well. The question is: Why were lambda expressions still failing when I removed them from the REST class and put them in a non-REST class? Just the fact I was including Jersey 1.x was enough to crash when using lambda expressions (whether or not an actual REST service was involved). But at any rate, I'm pleased the project is working again; I had been wanting to upgrade to the latest version of jax-rs & Jersey anyway so this forced me to do it (costing me several hours of work and need to explain to the "SCRUM master" why my estimate is off (don't get me started on that topic). Now if I can only figure out why Jersey 2 is returning XML when I told it to return JSON I'll be back on track.
Thanks everyone for your help!
Jersey 1.19 is compatible with JDK 1.8.0. Refer to
Jersey 1.19 Release summaryJDK8 support in Jersey 1.19Repackage ASM lib in Jersey 1.19
Please remove asm-3.1.jar since jersey-server-1.19.jar has asm 5.0 repacked in it.
The stacktrace shows that the class org.objectweb.asm.ClassReader.readClass gives an exception. I suppose this is a parser that Glassfish uses internally.
One of the reasons it would crash, is because it is not configured to handle the given input properly. In this case the given input is a lambda expression and it does not know how to handle it.
You will need to look for Java 8 bytecode (lambda) support for Glassfish and Tomcat. If it is not the issue, then it might be a bug in the parser that is internally used.
I had to upgrade spring to 4.3.6.RELEASE and junit to 4.12 before I got rid of this particular error when trying to run a junit test with java 1.8 after I had introduced lamdas.
In addition to all other answers,
On my system this problem is occured on Glassfish 4.0(build 89)
Solution;
I upgraded Glassfish to 4.1(build 13) and it solved that problem.

Categories