2

I'm trying to create a webservice that returns an int. It should also have an optional parameter - this fails.

This works:

package foo;

import java.util.Map;
import java.util.TreeMap;

import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

@Path("/euler")
public class Euler1 {

    @GET
    @Path("/getmultiples")
    @Produces(MediaType.APPLICATION_JSON)
    public static Map<String, Integer> getMultiples() {
        int sum = 0;
        int limit = 1000;
        for (int i = 0; i < limit; i += 3) {
            sum += i;
        }
        for (int i = 0; i < limit; i += 5) {
            if (i % 3 != 0) {
                sum += i;
            }
        }
        final Map<String, Integer> result = new TreeMap<>();
        result.put("Sum", sum);
        return result;
    }
}

If I call it like curl http://localhost:8080/foo/rest/euler/getmultiples I get {"Sum":233168}.


But the limit should be an optional parameter. So I change the method signature to

public static Map<String, Integer> getMultiples(
   @DefaultValue("1000") @QueryParam(value = "limit") int limit)

But then the previous returns nothing, and the server (Wildfly 8) logs

15:07:08,889 ERROR [io.undertow.request] (default task-3) UT005023: Exception handling request to /foo/rest/euler/getmultiples: java.lang.ArrayIndexOutOfBoundsException: 0
    at org.jboss.resteasy.plugins.validation.GeneralValidatorImpl.parametersResolveToSameTypes(GeneralValidatorImpl.java:515) [resteasy-validator-provider-11-3.0.10.Final.jar:]
    at org.jboss.resteasy.plugins.validation.GeneralValidatorImpl.overrides(GeneralValidatorImpl.java:486) [resteasy-validator-provider-11-3.0.10.Final.jar:]
    at org.jboss.resteasy.plugins.validation.GeneralValidatorImpl.getSuperMethod(GeneralValidatorImpl.java:444) [resteasy-validator-provider-11-3.0.10.Final.jar:]
    at org.jboss.resteasy.plugins.validation.GeneralValidatorImpl.getExecutableTypesOnMethodInHierarchy(GeneralValidatorImpl.java:335) [resteasy-validator-provider-11-3.0.10.Final.jar:]
    at org.jboss.resteasy.plugins.validation.GeneralValidatorImpl.isMethodValidatable(GeneralValidatorImpl.java:265) [resteasy-validator-provider-11-3.0.10.Final.jar:]

Here's the web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    version="3.1">
    <servlet-mapping>
        <servlet-name>javax.ws.rs.core.Application</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
</web-app>

The archetype used is the latest version of com.airhacks:javaee7-essentials-archetype.

Here's the 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>de.oneiros</groupId>
    <artifactId>webservice-ee7</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <finalName>webservice-ee7</finalName>
    </build>
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <failOnMissingWebXml>false</failOnMissingWebXml>
    </properties>
</project>

How can I pass an optional parameter to my method?

Martin Schröder
  • 4,176
  • 7
  • 47
  • 81
  • Just a shot in the dark, how does it hold up with varargs? This should allow 0 or more ints to be specified, then you just tell your code to use the first one. – ConMan Mar 04 '15 at 14:33
  • For better help post a [Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve) that demonstrates the problem. – Paul Samsotha Mar 04 '15 at 15:08
  • @peeskillet: I've added the web.xml. What more do you need? – Martin Schröder Mar 04 '15 at 15:19
  • Maybe the dependencies, actual method. The problem is not with the default value annotation, as it works fine. Just whatever information you feel is needed to reproduce the problem. – Paul Samsotha Mar 04 '15 at 15:23
  • @peeskillet: The default value annotation does not work here. – Martin Schröder Mar 04 '15 at 15:35
  • Here's what I did. I created a Maven webapp project. Added javaee dependency in provided scope. Added your web xml. Added a simple resource class with the same method signature but return Response (with the default value) instead. No need to test the Map. Ran it and it worked just fine. If you can't spot the problem, it helps to do this. Start a project from scratch adding in bit by bit til you hit the problem again. This is how you can narrow it down. Looks like a validation problem, but I don't see any sign of validation in your code, that has me wondering. – Paul Samsotha Mar 04 '15 at 15:45
  • According to http://www.mastertheboss.com/jboss-frameworks/resteasy/resteasy-tutorial-part-two-web-parameters#highlighter_576638 you may need to specify the `limit` parameter in the `@Path` annotation, e.g. : `@Path("/getmultiples/{limit}")`. Otherwise how do you intend to pass the limit value, when it is not set automatically? – Grégoire C Mar 04 '15 at 15:52
  • 1
    @geceo: Eclipse tells me that that's only needed for `@PathParams`, not `@QueryParams` – Martin Schröder Mar 04 '15 at 15:55
  • I take back part of my comment. I actually used a `Application` subclass rather than a web.xml, but only because your web.xml is lacking some things that caused a 404s, which is not your problem. – Paul Samsotha Mar 04 '15 at 16:07
  • @peeskillet: Then it must be in the pom. The archetype I'm using is `com.airhacks:javaee7-essentials-archetype`. Should I add the `pom.xml`? – Martin Schröder Mar 04 '15 at 16:08
  • Yes please. And the archetype version (if there is one). Let me try and pull it up – Paul Samsotha Mar 04 '15 at 16:09
  • 1
    Is it even allowed to have `static` subresource method? I think that could cause conflicts with injected paremters or instance fields – kapex Mar 04 '15 at 16:12
  • @kapep: Works perfectly without any parameters. – Martin Schröder Mar 04 '15 at 16:13
  • @peeskillet: Added the pom. TIA. – Martin Schröder Mar 04 '15 at 16:15
  • @kapep You're right. Tested with `static` and got the same thing. You should post it as an answer. – Paul Samsotha Mar 04 '15 at 16:17

2 Answers2

2

It seems the issue is that the resource method is static (thanks to @peeskillet for testing and confirming).

The stack trace indicates that something is wrong here: It calls a method named getSuperMethod which doesn't really make sense for static methods.

Looking at the source code, it seems the validator plugin is trying to use instance methods instead of a class methods. This sound like a bug in the plugin.

kapex
  • 28,903
  • 6
  • 107
  • 121
1

In fact, I can't reproduce your problem. I just provide here the configuration I use to test hoping that it would be useful for you.

My maven configuration:

<project (...)>
    <modelVersion>4.0.0</modelVersion>
    <groupId>resteasy.test</groupId>
    <artifactId>JAXRS-RESTEasy</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <java-version>1.7</java-version>
        <resteasy-version>3.0.10.Final</resteasy-version>
        <wtp-version>2.0</wtp-version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-jaxrs</artifactId>
            <version>${resteasy-version}</version>
        </dependency>

        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-servlet-initializer</artifactId>
            <version>${resteasy-version}</version>
        </dependency>
    </dependencies>

    <repositories>
        <repository>
            <id>JBoss repository</id>
            <url>https://repository.jboss.org/nexus/content/groups/public-jboss/</url>
        </repository>
    </repositories>
    (...)
</project>

My file web.xml:

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
    <display-name>JAXRS-RESTEasy</display-name>
</web-app>

My file javax.servlet.ServletContainerInitializer under the folder WEB-INF/services:

org.jboss.resteasy.plugins.servlet.ResteasyServletInitializer

My application class:

@ApplicationPath("/")
public class RESTEasyApplication extends Application {

}

My resource class:

@Path("/RESTEasyHelloWorld")
public class RESTEasyHelloWorldService {
    @GET
    @Path("/{pathParameter}")
    public Response responseMsg( @PathParam("pathParameter") String pathParameter,
        @DefaultValue("1000") @QueryParam("queryParameter") int queryParameter) {

        String response = "Hello from: " + pathParameter + " : " + queryParameter;

        return Response.status(200).entity(response).build();
    }
}

If I don't pass the query parameter queryParameter, I get the value 1000 in the method parameter queryParameter of type int.

Edited: I added static to the method responseMsg and it still works on my side... Really strange problem :-/ I made my test with version 3.0.10.Final within a Tomcat 7.

Hope it will help you to fix your problem! Thierry

Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • 1
    I reproduced the problem using Wildfly, as the OP is using. The problem happens on startup. Seems to be during validation (maybe of "correctness") of the resource model. – Paul Samsotha Mar 05 '15 at 01:05
  • 1
    The problem seems to be with the [resteasy validator provider](http://docs.jboss.org/resteasy/docs/3.0.7.Final/userguide/html/Validation.html#d4e2476) artifact. I don't think resteasy-jaxrs pulls that in. You may need to explicitly add it. It comes with Wildfly. I don't know if just addig the artifact to your dependencies will reproduce the problem, but you can try it – Paul Samsotha Mar 05 '15 at 01:12