0

I am trying to write a Junit test case for Spring and after a lot of reading I got everything working for a method that returns text/plain. When I tried to return application/json I ran into issues.

The consensus on SO seems to be: use mvc:annotation-driven. I tried this (by creating spring-web-servlet.xml shown below according to here. That didn't solve my issue however. Anyone know what I'm still doing wrong?

spring-web-servlet.xml (in WEB-INF folder)

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.2.xsd">

    <mvc:resources mapping="/resources/**" location="/resources/" />

    <mvc:annotation-driven />

</beans>

The method in question (in class HelloService)

@GET
@RequestMapping("/json2")
@Produces({"application/json"})
@ResponseBody
public Object getUserInfoJSON(@RequestParam(value="p",defaultValue="0") Integer userId){
    try (Connection conn = conn()) {
        String query = "SELECT * FROM pulse.customer WHERE userId = ?";
        PreparedStatement preparedStmt = conn.prepareStatement(query);
        preparedStmt.setInt(1, userId);
        ResultSet rs=preparedStmt.executeQuery();
        if(rs.next())
            return Json.createObjectBuilder().add("login name", rs.getString("loginName"));

            return Json.createObjectBuilder().add("login name", "shit broke yo!!!");
    }
    catch(SQLException s){
        return "sql exception:"+s.toString();
    }
    catch (NoResultException nre) {
        //throw new UserNotFoundException(userId);
        return "UserNotFoundException";
    } catch (PersistenceException e) {
        //throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
        return "WebApplicationException";
    }
}

The Junit test method (the version that takes in String works perfectly)

   @Test
    public void testUserInfoResponseJSON() throws Exception{

      MvcResult result=mockMvc.perform(get("/helloservice/json2?p=103")
              .contentType(MediaType.APPLICATION_JSON))
              .andExpect(status().isOk())
              .andExpect(content().contentTypeCompatibleWith("application/json"))
              .andReturn();

      String content = result.getResponse().getContentAsString();

      assertNotNull(content,"{login name:jbray}");
   } 

If needed, heres my pom.xml

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId> 
        <version>1.5.6.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.mariadb.jdbc/mariadb-java-client -->
        <dependency>
            <groupId>org.mariadb.jdbc</groupId>
            <artifactId>mariadb-java-client</artifactId>
        </dependency>
        <!-- Adding RESTEasy support to Bean Validations -->
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-validator-provider-11</artifactId>
            <version>3.1.4.Final</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.jboss.resteasy/resteasy-links -->
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-links</artifactId>
            <version>3.1.4.Final</version>
            <scope>provided</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.6.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.ehcache/ehcache -->
        <dependency>
            <groupId>org.ehcache</groupId>
            <artifactId>ehcache</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
          <groupId>javax.cache</groupId>
          <artifactId>cache-api</artifactId>
        </dependency>
                      <!--SPRING-->
        <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>
        <dependency>
            <groupId>com.paypal.springboot</groupId>
            <artifactId>resteasy-spring-boot-starter</artifactId>
            <version>2.3.3-RELEASE</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId> 
        </dependency>

        <!--JUNIT-->
        <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest-library</artifactId>
    <version>1.3</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.3.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>4.3.0.RELEASE</version>
    <scope>test</scope>
</dependency>

<!-- https://mvnrepository.com/artifact/org.json/json -->
<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20160810</version>
</dependency>

<dependency>
  <groupId>org.glassfish</groupId>
  <artifactId>javax.json</artifactId>
  <version>1.0.4</version>
</dependency>

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.4.1</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.4.1.1</version>
</dependency>
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-core-asl</artifactId>
    <version>1.9.13</version>
</dependency>

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.13</version>
</dependency>

<dependency>
     <groupId>com.jayway.jsonpath</groupId>
    <artifactId>json-path</artifactId>
    <scope>test</scope>
 </dependency>

    </dependencies>
Rilcon42
  • 9,584
  • 18
  • 83
  • 167
  • Please check https://stackoverflow.com/a/30549204/3530898, you need to add converter to convert java object to JSON and vice versa ` ` – Amit K Bist Sep 06 '17 at 22:36
  • I added the converter to spring-web-xml, but that didnt seem to help. I also experimented to using ResponseEntity based on the post you linked. Couldn't get it working tho. – Rilcon42 Sep 06 '17 at 22:53
  • If you get it working I would appreciate you sharing the code because I may have just misunderstood/mis-implemented your suggestion when I tested it – Rilcon42 Sep 06 '17 at 22:56
  • Did u get any exception? – Lijin Sep 06 '17 at 23:00
  • I will try to run your code but can you first try to keep jackson-databind, jackson-core and jackson-databind versions same and also add dependency for jackson-annotations, I am using 2.8.7 in my code – Amit K Bist Sep 06 '17 at 23:16

1 Answers1

0

I saw your dependency and your code in detail and found that you are using Glassfish's provider implementation of the JSR 353. those classes are org.glassfish.json.JsonObjectBuilderImpl$JsonObjectImpl, org.glassfish.json.JsonStringImpl, and org.glassfish.json.JsonNumberImpl, and javax.json.JsonValue$3 (an anonymous class for the value FALSE).

You need to change below code

return Json.createObjectBuilder().add("login name", rs.getString("loginName"));

return Json.createObjectBuilder().add("login name", "shit broke yo!!!");

to

return Json.createObjectBuilder().add("login name", rs.getString("loginName")).build().toString();

return Json.createObjectBuilder().add("login name", "shit broke yo!!!").build().toString();

and change return type of to getUserInfoJSON() method to String. Detailed explanation of JSR 353 classes and it mapping to ObjectMapper is available at https://stackoverflow.com/a/19205116/3530898

Amit K Bist
  • 6,760
  • 1
  • 11
  • 26
  • I am trying to have the method return a JSON object, how does returning a String help? Are strings parsed as JSON? – Rilcon42 Sep 07 '17 at 16:09
  • If you return JSONObject then it is like a map then you will see response like below `{ "login name": { "chars": "shit broke yo!!!", "string": "shit broke yo!!!", "valueType": "STRING" } }` – Amit K Bist Sep 07 '17 at 16:23
  • And you were only trying to return object of `JsonObjectBuilder` as you were not calling the build() on `JSONObjectBuilder` class. To return JsonObject you need to call build() method. – Amit K Bist Sep 07 '17 at 16:40