Let me start by saying I’m learning Java, and come from the .NET/C# world.
TL;DR:
This syntax does not work in VSCode or Eclipse IDE, does in IntelliJ. Why? What am I missing?
import path.to.class.Foo;
import path.to.class.Foo_; // cannot be resolved error
...
Foo_.barID; // cannot resolve to a variable
The underscore_ notation just causes the above errors… ugh
Long version:
I work on an API, and my team is newer to the project. None of us JAVA specific devs, and we’ve learned a ton over the last several months. The original devs created the project using IntelliJ, and supported it using that IDE. Unfortunately, our IntelliJ licenses keep being allowed to expire and it takes a week to get it back, and I’m not good with down time, so I tried Eclipse and VSCode. When trying to debug, the project won’t build because some imports are unable to be resolved, as well as some variables that appear to be using JPA 2.0 notation for Dynamic, typesafe queries.
Reading the following, this notation appears to have been around a long time, and Eclipse a long time Java IDE, so I think I’m clearly missing something.
What does an underscore concatenated to a class name mean?
https://developer.ibm.com/articles/j-typesafejpa/#N102F2
https://developer.ibm.com/articles/j-typesafejpa/
I have a hard time believing this is only possible in IntelliJ, so it has to be something I’m missing within the IDE’s. A package, or setting, or something that is not allowing the IDE to utilize the Criteria API?
pom.xml file as requested:
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>foo-app</artifactId>
<groupId>foo.bar.app</groupId>
<version>0.4.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>bar-api</artifactId>
<name>Public Facing API</name>
<properties>
<mainClass>foo.bar.fib.api.ApiService</mainClass>
<jjwt.version>0.11.4</jjwt.version>
</properties>
<dependencies>
<dependency>
<groupId>foo.bar.fib</groupId>
<artifactId>fib-testing</artifactId>
<version>0.4.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-core</artifactId>
</dependency>
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-client</artifactId>
</dependency>
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-migrations</artifactId>
</dependency>
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-hibernate</artifactId>
</dependency>
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-auth</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
<dependency>
<groupId>com.hubspot.dropwizard</groupId>
<artifactId>dropwizard-guicier</artifactId>
</dependency>
<dependency>
<groupId>${typesafe.config.groupID}</groupId>
<artifactId>typesafe-dropwizard-configuration</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
<dependency>
<groupId>foo.bar.fib</groupId>
<artifactId>fib-queue</artifactId>
<version>0.4.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>foo.bar.fib</groupId>
<artifactId>fib-common</artifactId>
<version>0.4.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>foo.bar.fib</groupId>
<artifactId>fib-tokens</artifactId>
<version>0.4.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>foo.bar.fib</groupId>
<artifactId>fib-buttonstuff</artifactId>
<version>0.4.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${hapi.fhir.groupID}</groupId>
<artifactId>hapi-fhir-client</artifactId>
</dependency>
<dependency>
<groupId>com.jakewharton.fliptables</groupId>
<artifactId>fliptables</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>${bouncey.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>${bouncey.version}</version>
</dependency>
<dependency>
<groupId>${hapi.fhir.groupID}</groupId>
<artifactId>hapi-fhir-structures-r4</artifactId>
</dependency>
<dependency>
<groupId>${hapi.fhir.groupID}</groupId>
<artifactId>hapi-fhir-validation-resources-dstu3</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.helger</groupId>
<artifactId>ph-schematron</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>${jjwt.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>${jjwt.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>${jjwt.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>2.9.3</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>com.newrelic.agent.java</groupId>
<artifactId>newrelic-java</artifactId>
<version>${newrelic.agent.version}</version>
<type>${newrelic.agent.type}</type>
</dependency>
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-json-logging</artifactId>
</dependency>
<!--Test resources-->
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-testing</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>2.31</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.0</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>${project.basedir}/../src/main/resources</directory>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<testResources>
<testResource>
<directory>${project.basedir}/../src/main/resources</directory>
</testResource>
<testResource>
<directory>src/test/resources</directory>
</testResource>
</testResources>
<plugins>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<configuration>
<createDependencyReducedPom>true</createDependencyReducedPom>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>${mainClass}</mainClass>
</transformer>
</transformers>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<shadedArtifactAttached>true</shadedArtifactAttached>
<finalName>${project.artifactId}</finalName>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>${mainClass}</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<configuration>
<container>
<args>
<arg>server</arg>
</args>
<ports>
<port>8080</port>
</ports>
<environment>
<DB_MIGRATION>1</DB_MIGRATION>
</environment>
<entrypoint>/entrypoint.sh</entrypoint>
</container>
<extraDirectories>
<paths>
<path>${project.basedir}/../bbcerts</path>
<path>${project.basedir}/target/jacoco-agent</path>
<path>${project.basedir}/docker</path>
<path>${project.basedir}/../src/main/resources/keypair</path>
<path>${project.basedir}/target/newrelic-agent</path>
</paths>
<permissions>
<permission>
<file>/entrypoint.sh</file>
<mode>755</mode>
</permission>
</permissions>
</extraDirectories>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<annotationProcessorPath>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<version>5.4.2.Final</version>
</annotationProcessorPath>
<path>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</path>
<path>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.1</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
EDIT: No longer monitoring this question since using the Community Edition of IntelliJ IDEA will work for my needs and I do not have to switch IDE’s. I think the proposed answer will work for some, if not most; however, since I was unable (and unwilling to continue) to make the build work with another IDE I am leaving it unselected as the solution.
2
Answers
Use the Community Edition of IntelliJ as offered by @joopeggen. Proposed answer by @e-riz is a likely secondary answer.
Those are so-called metamodel classes for your entities, and they are generated by Hibernate (since you have the
hibernate-jpamodelgen
annotation processor configured in the pom). So whenever a maven build is run, those classes are generated to a specific directory, and then Maven includes that directory with as a source location during the compile step.Since Eclipse (and VSCode, I presume) aren’t aware of this folder of generated files as a source location for the project, it doesn’t recognize the generated classes. There are a couple of ways to deal with it:
You can configure the annotation processor in Eclipse so that it does the same thing as the Maven plugin. It’s pretty straightfoward, but requires a one-time manual setup. A decent set of instructions is found here; the official JBoss Hibernate instructions are pretty dated, but might still be valid, found here (there’s also a decent explanation of Hibernate’s metamodel generation on that page, for reference).
You can rely on Maven to run the generator and just add the output folder as a source location to your Eclipse project. The default output location for APT-generated files in Maven is "target/generated-sources/apt", so you can add that to the Eclipse project’s Build Path as a source folder. You can do that in the project’s Properties, Java Build Path section; or just right-click on the folder and select Build Path > Use as Source Folder
.
Note that with option 2, when you change your entities you’ll have to re-run the maven build (at least generate-sources phase) to see the updated generated classes.