Skip to content
This repository has been archived by the owner on Mar 29, 2019. It is now read-only.

Commit

Permalink
Refactored to allow view extension options
Browse files Browse the repository at this point in the history
This refactoring removes the hard requirement that controller methods
provide JSON for REST.  This paves the way to allow users to configure
the ViewResolver of their choice.
  • Loading branch information
mminella committed May 27, 2015
1 parent 6f4b847 commit 725ba93
Show file tree
Hide file tree
Showing 10 changed files with 166 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@
import org.springframework.hateoas.PagedResources;
import org.springframework.hateoas.PagedResources.PageMetadata;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

/**
* Controller for batch job executions.
Expand All @@ -58,7 +58,7 @@
* @author Gunnar Hillert
* @since 2.0
*/
@RestController
@Controller
@RequestMapping("/batch/executions")
@ExposesResourceFor(JobExecutionInfoResource.class)
public class BatchJobExecutionsController extends AbstractBatchJobsController {
Expand All @@ -74,7 +74,7 @@ public class BatchJobExecutionsController extends AbstractBatchJobsController {
* @param pageable If not provided will default to page 0 and a page size of 20
* @return Collection of JobExecutionInfoResource
*/
@RequestMapping(value = { "" }, method = RequestMethod.GET, produces = "application/json")
@RequestMapping(value = { "" }, method = RequestMethod.GET)
@ResponseStatus(HttpStatus.OK)
public PagedResources<JobExecutionInfoResource> list(Pageable pageable) throws NoSuchJobException {

Expand All @@ -101,7 +101,7 @@ public PagedResources<JobExecutionInfoResource> list(Pageable pageable) throws N
* @param pageSize page size for the list
* @return collection of JobExecutionInfo
*/
@RequestMapping(value = "", method = RequestMethod.GET, params = "jobname", produces = "application/json")
@RequestMapping(value = "", method = RequestMethod.GET, params = "jobname")
@ResponseStatus(HttpStatus.OK)
public Collection<JobExecutionInfoResource> executionsForJob(@RequestParam("jobname") String jobName,
@RequestParam(defaultValue = "0") int startJobExecution,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,20 @@
import org.springframework.batch.core.launch.NoSuchJobInstanceException;
import org.springframework.hateoas.ExposesResourceFor;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

/**
* Controller for batch job instances.
*
* @author Ilayaperumal Gopinathan
* @since 2.0
*/
@RestController
@Controller
@RequestMapping("/batch/instances")
@ExposesResourceFor(JobInstanceInfoResource.class)
public class BatchJobInstancesController extends AbstractBatchJobsController {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@
import org.springframework.hateoas.ExposesResourceFor;
import org.springframework.hateoas.PagedResources;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;


/**
Expand All @@ -48,7 +48,7 @@
* @since 2.0
*
*/
@RestController
@Controller
@RequestMapping("/batch/configurations")
@ExposesResourceFor(DetailedJobInfoResource.class)
public class BatchJobsController extends AbstractBatchJobsController {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@
import org.springframework.batch.core.launch.NoSuchJobExecutionException;
import org.springframework.hateoas.ExposesResourceFor;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

/**
* Controller for returning Batch {@link org.springframework.batch.core.StepExecution}s.
Expand All @@ -43,7 +43,7 @@
* @author Ilayaperumal Gopinathan
* @since 2.0
*/
@RestController
@Controller
@RequestMapping("/batch/executions/{jobExecutionId}/steps")
@ExposesResourceFor(StepExecutionInfoResource.class)
public class BatchStepExecutionsController extends AbstractBatchJobsController {
Expand All @@ -55,7 +55,7 @@ public class BatchStepExecutionsController extends AbstractBatchJobsController {
* @return Collection of {@link StepExecutionInfoResource} for the given jobExecutionId
* @throws org.springframework.batch.core.launch.NoSuchJobExecutionException Thrown if the respective {@link org.springframework.batch.core.JobExecution} does not exist
*/
@RequestMapping(value = { "" }, method = RequestMethod.GET, produces = "application/json")
@RequestMapping(value = { "" }, method = RequestMethod.GET)
@ResponseStatus(HttpStatus.OK)
public Collection<StepExecutionInfoResource> list(@PathVariable("jobExecutionId") long jobExecutionId) throws NoSuchJobExecutionException {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.admin.web;

import java.util.Locale;

import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

/**
* @author Michael Minella
*/
public class JsonViewResolver implements ViewResolver {
/**
* Get the view to use.
*
* @return Always returns an instance of {@link MappingJackson2JsonView}.
*/
@Override
public View resolveViewName(String viewName, Locale locale) throws Exception {
MappingJackson2JsonView view = new MappingJackson2JsonView();
view.setPrettyPrint(true); // Lay the JSON out to be nicely readable
return view;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,15 @@

package org.springframework.batch.admin.web;

import java.util.ArrayList;
import java.util.List;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.view.ContentNegotiatingViewResolver;

/**
* Takes care of infrastructure setup for the web/rest layer.
Expand Down Expand Up @@ -51,4 +57,23 @@ public BatchJobsController batchJobsController() {
public BatchStepExecutionsController batchStepExecutionsController() {
return new BatchStepExecutionsController();
}

@Bean
public ViewResolver jsonViewResolver() {
return new JsonViewResolver();
}

@Bean
public ViewResolver contentNegotiatingViewResolver(ContentNegotiationManager manager) {
// Define the view resolvers
List<ViewResolver> resolvers = new ArrayList<ViewResolver>();

resolvers.add(jsonViewResolver());

// Create the CNVR plugging in the resolvers and the content-negotiation manager
ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
resolver.setViewResolvers(resolvers);
resolver.setContentNegotiationManager(manager);
return resolver;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,21 +99,21 @@ public void testGetJobExecutionsByName() throws Exception {
mockMvc.perform(
get("/batch/executions").param("jobname", "job1")
.param("startJobExecution", "0").param("pageSize", "20").accept(
MediaType.APPLICATION_JSON)).andExpect(status().isOk())
.andExpect(jsonPath("$[1][*]", Matchers.hasSize(1)))
.andExpect(jsonPath("$[1][*].executionId").value(3))
.andExpect(jsonPath("$[1][*].jobId").value(2))
MediaType.APPLICATION_JSON)).andDo(print()).andExpect(status().isOk())
.andExpect(jsonPath("$.[*]", Matchers.hasSize(1)))
.andExpect(jsonPath("$.[*][0].executionId").value(3))
.andExpect(jsonPath("$.[*][0].jobId").value(2))
.andExpect(
jsonPath("$[1][*].jobParameters.parameters.param1.value").value("test"))
jsonPath("$.[*][0].jobParameters.parameters.param1.value").value("test"))
.andExpect(
jsonPath("$[1][*].jobParameters.parameters.param1.type").value("STRING"))
.andExpect(jsonPath("$[1][*].jobParameters.parameters.param1.identifying").value(
jsonPath("$.[*][0].jobParameters.parameters.param1.type").value("STRING"))
.andExpect(jsonPath("$.[*][0].jobParameters.parameters.param1.identifying").value(
true))
.andExpect(
jsonPath("$[1][*].jobParameters.parameters.param2.value[1]").value(123))
jsonPath("$.[*][0].jobParameters.parameters.param2.value").value(123))
.andExpect(
jsonPath("$[1][*].jobParameters.parameters.param2.type").value("LONG"))
.andExpect(jsonPath("$[1][*].jobParameters.parameters.param2.identifying").value(
jsonPath("$.[*][0].jobParameters.parameters.param2.type").value("LONG"))
.andExpect(jsonPath("$.[*][0].jobParameters.parameters.param2.identifying").value(
false));
}

Expand All @@ -126,17 +126,16 @@ public void testGetBatchJobExecutions() throws Exception {
mockMvc.perform(
get("/batch/executions").accept(
MediaType.APPLICATION_JSON)).andDo(print()).andExpect(status().isOk())
.andExpect(jsonPath("$.content[1]", Matchers.hasSize(2)))
.andExpect(jsonPath("$.content[1][*].executionId", contains(0, 3)))
.andExpect(jsonPath("$.content[1][*].stepExecutions", Matchers.hasSize(2)))
.andExpect(jsonPath("$.content[1][*].jobId", contains(0, 2)))
.andExpect(jsonPath("$.content[1][*].jobParameters.parameters.param1.value", contains("test", "test")))
.andExpect(jsonPath("$.content[1][*].jobParameters.parameters.param1.type", contains("STRING", "STRING")))
.andExpect(jsonPath("$.content[1][*].jobParameters.parameters.param1.identifying", contains(true, true)))
.andExpect(jsonPath("$.content[1][*].jobParameters.parameters.param2.value[1]", Matchers.hasSize(2)))
.andExpect(jsonPath("$.content[1][*].jobParameters.parameters.param2.value[1]", contains(123, 123)))
.andExpect(jsonPath("$.content[1][*].jobParameters.parameters.param2.type", contains("LONG", "LONG")))
.andExpect(jsonPath("$.content[1][*].jobParameters.parameters.param2.identifying", contains(false, false)));
.andExpect(jsonPath("$.pagedResources.content", Matchers.hasSize(2)))
.andExpect(jsonPath("$.pagedResources.content[*].executionId", contains(0, 3)))
.andExpect(jsonPath("$.pagedResources.content[*].stepExecutions", Matchers.hasSize(2)))
.andExpect(jsonPath("$.pagedResources.content[*].jobId", contains(0, 2)))
.andExpect(jsonPath("$.pagedResources.content[*].jobParameters.parameters.param1.value", contains("test", "test")))
.andExpect(jsonPath("$.pagedResources.content[*].jobParameters.parameters.param1.type", contains("STRING", "STRING")))
.andExpect(jsonPath("$.pagedResources.content[*].jobParameters.parameters.param1.identifying", contains(true, true)))
.andExpect(jsonPath("$.pagedResources.content[*].jobParameters.parameters.param2.value", contains(123, 123)))
.andExpect(jsonPath("$.pagedResources.content[*].jobParameters.parameters.param2.type", contains("LONG", "LONG")))
.andExpect(jsonPath("$.pagedResources.content[*].jobParameters.parameters.param2.identifying", contains(false, false)));
}

@Test
Expand All @@ -148,7 +147,7 @@ public void testGetBatchJobExecutionsPaginated() throws Exception {
mockMvc.perform(
get("/batch/executions").param("page", "1").param("size", "5").accept(
MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andExpect(
jsonPath("$.content[*]", Matchers.hasSize(2)));
jsonPath("$.pagedResources.content[*]", Matchers.hasSize(2)));
}

@Test
Expand All @@ -157,17 +156,17 @@ public void testGetSingleBatchJobExecution() throws Exception {
when(jobLocator.getJob("job1")).thenReturn(new JobSupport("job1"));

mockMvc.perform(
get("/batch/executions/0").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk())
.andExpect(jsonPath("$.executionId", Matchers.is(0)))
.andExpect(jsonPath("$.jobParameters.parameters.param1.type", Matchers.is("STRING")))
.andExpect(jsonPath("$.jobParameters.parameters.param1.identifying", Matchers.is(true)))
.andExpect(jsonPath("$.jobParameters.parameters.param1.value", Matchers.is("test")))
.andExpect(jsonPath("$.jobParameters.parameters.param2.type", Matchers.is("LONG")))
.andExpect(jsonPath("$.jobParameters.parameters.param2.identifying", Matchers.is(false)))
.andExpect(jsonPath("$.jobParameters.parameters.param2.value[1]", Matchers.is(123)))
.andExpect(jsonPath("$.stepExecutions", Matchers.hasSize(2)))
.andExpect(jsonPath("$.stepExecutionCount", Matchers.is(2)))
.andExpect(jsonPath("$.name", Matchers.is("job1")));
get("/batch/executions/0").accept(MediaType.APPLICATION_JSON)).andDo(print()).andExpect(status().isOk())
.andExpect(jsonPath("$.jobExecutionInfoResource.executionId", Matchers.is(0)))
.andExpect(jsonPath("$.jobExecutionInfoResource.jobParameters.parameters.param1.type", Matchers.is("STRING")))
.andExpect(jsonPath("$.jobExecutionInfoResource.jobParameters.parameters.param1.identifying", Matchers.is(true)))
.andExpect(jsonPath("$.jobExecutionInfoResource.jobParameters.parameters.param1.value", Matchers.is("test")))
.andExpect(jsonPath("$.jobExecutionInfoResource.jobParameters.parameters.param2.type", Matchers.is("LONG")))
.andExpect(jsonPath("$.jobExecutionInfoResource.jobParameters.parameters.param2.identifying", Matchers.is(false)))
.andExpect(jsonPath("$.jobExecutionInfoResource.jobParameters.parameters.param2.value", Matchers.is(123)))
.andExpect(jsonPath("$.jobExecutionInfoResource.stepExecutions", Matchers.hasSize(2)))
.andExpect(jsonPath("$.jobExecutionInfoResource.stepExecutionCount", Matchers.is(2)))
.andExpect(jsonPath("$.jobExecutionInfoResource.name", Matchers.is("job1")));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,12 @@ public void testGetJobInstanceByInstanceId() throws Exception {

mockMvc.perform(
get("/batch/instances/0").accept(MediaType.APPLICATION_JSON)).andDo(print()).andExpect(status().isOk())
.andExpect(jsonPath("$.instanceId").value(0))
.andExpect(jsonPath("$.jobName").value("job1"))
.andExpect(jsonPath("$.jobExecutions[1]", Matchers.hasSize(1)))
.andExpect(jsonPath("$.jobExecutions[1][0].executionId").value(3))
.andExpect(jsonPath("$.jobExecutions[1][0].stepExecutions[1]", Matchers.hasSize(1)))
.andExpect(jsonPath("$.jobExecutions[1][0].stepExecutions[1][0].stepName").value("s1"));
.andExpect(jsonPath("$.jobInstanceInfoResource.instanceId").value(0))
.andExpect(jsonPath("$.jobInstanceInfoResource.jobName").value("job1"))
.andExpect(jsonPath("$.jobInstanceInfoResource.jobExecutions", Matchers.hasSize(1)))
.andExpect(jsonPath("$.jobInstanceInfoResource.jobExecutions[0].executionId").value(3))
.andExpect(jsonPath("$.jobInstanceInfoResource.jobExecutions[0].stepExecutions", Matchers.hasSize(1)))
.andExpect(jsonPath("$.jobInstanceInfoResource.jobExecutions[0].stepExecutions[0].stepName").value("s1"));
}

@Test
Expand All @@ -98,10 +98,10 @@ public void testGetJobInstanceByJobName() throws Exception {

mockMvc.perform(
get("/batch/instances").param("jobname", "job1").param("startJobInstance", "0").param("pageSize", "20").accept(
MediaType.APPLICATION_JSON)).andExpect(status().isOk())
.andExpect(jsonPath("$[1]", Matchers.hasSize(2)))
.andExpect(jsonPath("$[1][*].instanceId", contains(0, 3)))
.andExpect(jsonPath("$[1][*].jobName", contains("job1", "job1")));
MediaType.APPLICATION_JSON)).andDo(print()).andExpect(status().isOk())
.andExpect(jsonPath("$.jobInstanceInfoResourceList", Matchers.hasSize(2)))
.andExpect(jsonPath("$.jobInstanceInfoResourceList[*].instanceId", contains(0, 3)))
.andExpect(jsonPath("$.jobInstanceInfoResourceList[*].jobName", contains("job1", "job1")));
}

@Test
Expand Down
Loading

0 comments on commit 725ba93

Please sign in to comment.