/*
* COMSAT
* Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.
*
* This program and the accompanying materials are dual-licensed under
* either the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation
*
* or (per the licensee's choosing)
*
* under the terms of the GNU Lesser General Public License version 3.0
* as published by the Free Software Foundation.
*/
/*
* Based on the corresponding class in Spring Boot Samples.
* Copyright the original author(s).
* Released under the ASF 2.0 license.
*/
package comsat.sample.actuator;
import co.paralleluniverse.fibers.Fiber;
import co.paralleluniverse.fibers.SuspendExecution;
import co.paralleluniverse.fibers.Suspendable;
import co.paralleluniverse.strands.SuspendableCallable;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Description;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.async.DeferredResult;
@Controller
@Description("A controller for handling requests for hello messages")
public class SampleController {
@Autowired
private HelloWorldService helloWorldService;
private Callable<Map<String, String>> helloCallable(final DeferredResult<Map<String, String>> optDeferred) throws SuspendExecution {
return new Callable<Map<String, String>>() {
@Override
@Suspendable
public Map<String, String> call() throws Exception {
try {
Fiber.sleep(10);
Map<String, String> ret = Collections.singletonMap("message", helloWorldService.getHelloMessage());
if (optDeferred != null) optDeferred.setResult(ret);
return ret;
} catch (Throwable t) {
if (optDeferred != null) optDeferred.setErrorResult(t);
throw t;
}
}
};
}
@RequestMapping(value = "/callable", method = RequestMethod.GET)
@ResponseBody
public Callable<Map<String, String>> helloCallable() throws SuspendExecution {
return helloCallable(null);
}
@RequestMapping(value = "/deferred", method = RequestMethod.GET)
@ResponseBody
public DeferredResult<Map<String, String>> helloDeferred() {
final DeferredResult<Map<String, String>> ret = new DeferredResult<>();
new Fiber(new SuspendableCallable<Map<String, String>>() {
@Override
public Map<String, String> run() throws SuspendExecution, InterruptedException {
try {
return helloCallable(ret).call();
} catch (Exception ex) {
ret.setErrorResult(ret);
throw new RuntimeException(ex);
}
}
}).start();
return ret;
}
private Callable<Map<String, Object>> ollehCallable(final Message message, final DeferredResult<Map<String, Object>> optDeferred) throws SuspendExecution {
return new Callable<Map<String, Object>>() {
@Override
@Suspendable
public Map<String, Object> call() throws Exception {
try {
Fiber.sleep(10);
Map<String, Object> model = new LinkedHashMap<>();
model.put("message", message.getValue());
model.put("title", "Hello Home");
model.put("date", new Date());
if (optDeferred != null) optDeferred.setResult(model);
return model;
} catch (Throwable t) {
if (optDeferred != null) optDeferred.setErrorResult(t);
throw t;
}
}
};
}
@RequestMapping(value = "/callable", method = RequestMethod.POST)
@ResponseBody
public Callable<Map<String, Object>> ollehCallable(final Message message) throws SuspendExecution {
return ollehCallable(message, null);
}
@RequestMapping(value = "/deferred", method = RequestMethod.POST)
@ResponseBody
public DeferredResult<Map<String, Object>> ollehDeferred(@Validated final Message message) {
final DeferredResult<Map<String, Object>> ret = new DeferredResult<>();
new Fiber(new SuspendableCallable<Map<String, Object>>() {
@Override
public Map<String, Object> run() throws SuspendExecution, InterruptedException {
try {
return ollehCallable(message, ret).call();
} catch (Exception ex) {
ret.setErrorResult(ret);
throw new RuntimeException(ex);
}
}
}).start();
return ret;
}
private Callable<String> fooCallable(final DeferredResult<String> optDeferred) throws SuspendExecution {
return new Callable<String>() {
@Override
@Suspendable
public String call() throws Exception {
try {
Fiber.sleep(10);
throw new IllegalArgumentException("Server error");
} catch (Throwable t) {
if (optDeferred != null) optDeferred.setErrorResult(t);
throw t;
}
}
};
}
@RequestMapping("/callable/foo")
@ResponseBody
public Callable<String> fooCallable() throws SuspendExecution {
return fooCallable(null);
}
@RequestMapping("/deferred/foo")
@ResponseBody
public DeferredResult<String> fooDeferred() {
final DeferredResult<String> ret = new DeferredResult<>();
new Fiber(new SuspendableCallable<String>() {
@Override
public String run() throws SuspendExecution, InterruptedException {
try {
return fooCallable(ret).call();
} catch (Exception ex) {
ret.setErrorResult(ret);
throw new RuntimeException(ex);
}
}
}).start();
return ret;
}
protected static class Message {
@NotBlank(message = "Message value cannot be empty")
private String value;
public String getValue() {
return this.value;
}
public void setValue(String value) {
this.value = value;
}
}
}