0

I'm struggling to get Guice to work with my Jersey/Grizzly classes. I started with console Java app, added Guice and got my injection working as well as my domain objects. Then I proceeded to add webservices through Jersey/Grizzly. As you might be able to tell from my coding style, I've come from a C# background. So I'm sure some of my struggle is learning Javas way of doing things.

What I want is that my non webservices classes can get injected into the webservices handlers so they can use the functionality I've built.

In my class below, I have a database instance handler I want to inject into the webservices classes:

@Path("/options")
public class OptionsServices {

    private IDatabaseService dbService;

    @Inject
    public void setService(IDatabaseService svc){
        this.dbService = svc;
    }


    @GET
    @Path("{symbol}")
    @Produces(MediaType.APPLICATION_JSON)
    public Quote getOptionQuote(@PathParam("symbol") String symbol) {
        // do stuff
    }
}

I tried adding in GuiceBridge and binding that in my extension of the ResourceConfig class. But no matter what version I used, I get some really crazy exceptions about missing properties when I tried to initialize the webservices. Simply removing GuiceBridge from my pom.xml removes the exception. It seems like its version compatibility problem but I am at a loss to understand what version of what library.

Exception in thread "main" java.lang.NoSuchMethodError: org.glassfish.hk2.utilities.general.GeneralUtilities.getSystemProperty(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
        at org.jvnet.hk2.internal.ServiceLocatorImpl.<clinit>(ServiceLocatorImpl.java:122)
        at org.jvnet.hk2.external.generator.ServiceLocatorGeneratorImpl.initialize(ServiceLocatorGeneratorImpl.java:66)
        at org.jvnet.hk2.external.generator.ServiceLocatorGeneratorImpl.create(ServiceLocatorGeneratorImpl.java:98)
        at org.glassfish.hk2.internal.ServiceLocatorFactoryImpl.internalCreate(ServiceLocatorFactoryImpl.java:312)
        at org.glassfish.hk2.internal.ServiceLocatorFactoryImpl.create(ServiceLocatorFactoryImpl.java:268)
        at org.glassfish.jersey.internal.inject.Injections._createLocator(Injections.java:138)
        at org.glassfish.jersey.internal.inject.Injections.createLocator(Injections.java:123)
        at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:308)
        at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:289)
        at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer.<init>(GrizzlyHttpContainer.java:334)
        at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory.createHttpServer(GrizzlyHttpServerFactory.java:122)
        at Application.Server.WebServer.startServer(WebServer.java:40)
        at Application.Server.WebServer.Start(WebServer.java:45)
        at Application.Startup.run(Startup.java:68)
        at Application.Startup.main(Startup.java:87)

And my pom.xml

<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">
    <modelVersion>4.0.0</modelVersion>
    <groupId>tatmancapital</groupId>
    <artifactId>ServerConsole</artifactId>
    <version>R1</version>

    <properties>
        <jersey.version>2.17</jersey.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.glassfish.jersey</groupId>
                <artifactId>jersey-bom</artifactId>
                <version>${jersey.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/com.google.inject/guice -->
        <dependency>
            <groupId>com.google.inject</groupId>
            <artifactId>guice</artifactId>
            <version>4.1.0</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.15</version>
            <exclusions>
                <exclusion>
                    <groupId>com.sun.jmx</groupId>
                    <artifactId>jmxri</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jdmk</groupId>
                    <artifactId>jmxtools</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>javax.jms</groupId>
                    <artifactId>jms</artifactId>
                </exclusion>
            </exclusions>           
        </dependency>       

        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.3</version>
        </dependency>

        <dependency>
            <groupId>commons-httpclient</groupId>
            <artifactId>commons-httpclient</artifactId>
            <version>3.1</version>
        </dependency>

        <dependency>
            <groupId>com.thoughtworks.xstream</groupId>
            <artifactId>xstream</artifactId>
            <version>1.4.9</version>
        </dependency>

        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.4</version>
        </dependency>

        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.0.4</version>
        </dependency>

        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-grizzly2-http</artifactId>
        </dependency>

        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-moxy</artifactId>
        </dependency>


        <dependency>
            <groupId>org.glassfish.hk2</groupId>
            <artifactId>guice-bridge</artifactId>
            <version>2.5.0-b32</version>
        </dependency>       

        <dependency>
            <groupId>commons-httpclient-ssl-contrib</groupId>
            <artifactId>commons-httpclient-ssl-contrib</artifactId>
            <version>3.1</version>
           <scope>system</scope>
           <systemPath>${project.basedir}/libs/commons-httpclient-contrib-ssl-3.1.jar</systemPath>
        </dependency>

        <dependency>
           <groupId>etrade</groupId>
           <artifactId>com.etrade.accounts</artifactId>
           <version>1.0</version>
           <scope>system</scope>
           <systemPath>${project.basedir}/libs/etws-accounts-sdk-1.0.jar</systemPath>
        </dependency>

        <dependency>
           <groupId>etrade</groupId>
           <artifactId>com.etrade.order</artifactId>
           <version>1.0</version>
           <scope>system</scope>
           <systemPath>${project.basedir}/libs/etws-order-sdk-1.0.jar</systemPath>
        </dependency>

        <dependency>
           <groupId>etrade</groupId>
           <artifactId>com.etrade.oauth</artifactId>
           <version>1.0</version>
           <scope>system</scope>
           <systemPath>${project.basedir}/libs/etws-oauth-sdk-1.0.jar</systemPath>
        </dependency>

        <dependency>
           <groupId>etrade</groupId>
           <artifactId>com.etrade.markets</artifactId>
           <version>1.0</version>
           <scope>system</scope>
           <systemPath>${project.basedir}/libs/etws-market-sdk-1.0.jar</systemPath>
        </dependency>

        <dependency>
           <groupId>etrade</groupId>
           <artifactId>com.etrade.common</artifactId>
           <version>1.0</version>
           <scope>system</scope>
           <systemPath>${project.basedir}/libs/etws-common-connections-1.0.jar</systemPath>
        </dependency>               

    </dependencies>

    <build>
      <plugins>     
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>3.0.0</version>
            <configuration>
                <archive>
                  <manifest>            
                    <mainClass>Application.Startup</mainClass>                  
                  </manifest>
                </archive>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
                <appendAssemblyId>false</appendAssemblyId>
                <finalName>ServerConsole-V1</finalName>
            </configuration>
            <executions>
                <execution>
                    <id>make-assembly</id> <!-- this is used for inheritance merges -->
                    <phase>package</phase> <!-- bind to the packaging phase -->
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>       
      </plugins>
    </build>
</project>

I apologize I cannot explain this problem with more definitive here's what is wrong. I may have architected my app completely wrong and given this is just me learning, I am ok with that. I would like to avoid rewriting my domain logic construction and unit tests.

Thank you for your help Matt

tatmanblue
  • 1,176
  • 2
  • 14
  • 30

1 Answers1

0

Error explanation

A java.lang.NoSuchMethodError is definitely an error with packages and library versions. It means that you have compiled code referencing a method that do not exist in your runtime code.

It's not an error commonly seen in your code because the compiler won't let you pass code referencing a non existent method. But in this case the code referencing the method and the referenced code are both libraries so that means that the code with the method reference was compiled against a different version of the target class.

Somehow this error is analogous to the more common ClassNotFoundException. But instead of not finding a class you are not finding a method inside a class.

Finding the source of your problem

Now you know what the problem is. Solving it, I'm afraid, is not that easy. Package managment and library resolution with Java is becoming harder every year. I see you are using the bom (Bill of Materials) for the Jersey library. Also, your pom file is not an easy one. I suggest you to build a test project only with the structure of your API (jax-rs) code with Guice and the HK2-Guice bridge. Maybe instead of using the BOM try this recent versions, they work for me:

  • com.google.inject:guice:4.1.0
  • org.glassfish.jersey.containers:jersey-container-servlet:2.25
  • org.glassfish.hk2:guice-bridge:2.5.+

I'm using the servlet container but you are using an standalone one. It doesn't matter, use yours but keep the version number.

Maven resolution

Also try to check which version of each package you are including in the final build. You may find useful this maven command to display the dependency tree:

https://maven.apache.org/plugins/maven-dependency-plugin/tree-mojo.html

sargue
  • 5,695
  • 3
  • 28
  • 43
  • This is a great explanation. I apologize this is a newbie question. How do I not use the BOM? – tatmanblue Feb 20 '17 at 16:39
  • @tatmanblue Easy. You remove the bom declaration and add a version to each dependency. The BOM is just a _meta-dependency_ which gives you exact versions. Look at `` declarations without ``. For more info see [http://stackoverflow.com/questions/14874966/how-to-use-bom-file-with-maven](this question). – sargue Feb 20 '17 at 16:59
  • Thank you. Removing the BOM, setting specific version numbers for the dependencies, as you called out, fixed my problem. I am now able to access my webservices from a browser without errors (I had to add one dependency for json serialization) – tatmanblue Feb 20 '17 at 19:48