Springboot REST endpoints with Alfresco Process Services (Activiti) - spring-boot

I have installed Alfresco Process Services on my local machine. I have also created a springboot project to write custom listeners like Task listener or execution listeners. These listeners are working fine. I create a jar file and put it into webapp\activiti-app\WEB-INF\lib folder.
Now I want to add REST endpoints in my application so that external users can directly take an action on task.
I added the following class beside my main application class which has the main method.
#RestController
#RequestMapping("/api2")
public class WorkflowController {
#RequestMapping("/greeting")
public String greeting(#RequestParam(value="name", defaultValue="World") String name) {
return "Hello from " +name;
}
}
The issue is when I try to access the endpoint via any of the below URL it gives me 404 error.
http://localhost:8081/activiti-app/api2/greeting
OR
http://localhost:8081/api2/greeting
Please help

To access the URL publicly you need to start your mapping with /enterprise. APS requires this to distinguish between public and private rest APIs, so your #RequestMapping("/api2") should be #RequestMapping("/enterprise/api2") which should then be accessible with http://localhost:8081/activiti-app/api/enterprise/api2/greeting. refer the developer series for a detailed example.

Related

Spring boot, tomcat, rest api 404

I am using Kotlin + Gradle and trying to build a war file to deploy on Tomcat. My application is from the https://start.spring.io plus a simple controller and build the war file using ./gradlew bootWar
#SpringBootApplication
class ServletInitializer : SpringBootServletInitializer() {
override fun configure(application: SpringApplicationBuilder): SpringApplicationBuilder {
return application.sources(DemoApplication::class.java)
}
}
#RestController
class TomcatController {
#GetMapping("/hello")
fun sayHello(): Collection<String> {
return IntStream.range(0, 10)
.mapToObj { i: Int -> "Hello number $i" }
.collect(Collectors.toList())
}
}
when I try to access it I get
Type Status Report
Message The requested resource [/demo-0.0.1-SNAPSHOT/hello] is not available
Description The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.
I am super stuck. What am I doing wrong? If I add a html file to the src/main/webapp/index.html it shows up for some reason only the rest api can't be reached.
Spring Boot applications come with a built in Servlet. You are probably already using this feature when launching the application inside your IDE.
This basically means that you can just run your .jar file on any web server and it will be ready to go without setting up an extra tomcat instance.
However, if you want to build a Spring Boot application as a war file and deploy it to an external tomcat, you need to follow some extra steps as explained in this article.
Assuming from what you posted so far: the path that is returned shows another route before your actual controller route "/demo-0.0.1-SNAPSHOT/hello" is this "/demo-0.0.1-SNAPSHOT" the path that your application runs on ? If not it should be included in your controller (assuming you havent set it elsewhere for e.g. in your application.properties).
for e.g. http://localhost:8080/ would be the basepath and either http://localhost:8080/demo-0.0.1-SNAPSHOT/hello or http://localhost:8080/hello would point to your controller. Also your startup logs (for Tomcat and Spring) might give away more about the issue.

Prevent direct call to my spring boot rest API

I have several REST services (on spring boot) used by a javascript file (website) and these services can be called directly by anyone (and you can see the API url/parameters with the developper console on any browser).
So I would like to prevent the direct calls to the API, exept of course from the front side of my app.
I saw that I can use an API key with spring security but is it reliable? Since I think you can see the key if you intercept the message with developper console.
What you can do are the following :
Disable CORS in your springboot application by setting the following globally or per endpoint as you wish.
To set the CORS per endpoint :
#CrossOrigin(origins = "http://localhost:9000")
#GetMapping("/greeting")
public Test testing(#RequestParam(required=false, defaultValue="Test") String name) {
System.out.println("in test");
return new Testing(10, String.format(template, name));
}
You can use spring security to preauthorize your controller endpoints to make sure that only the authorized has access to the controller.
Like for example :
#RestController
#RequestMapping({"/v2/"})
public class ExampleTestController {
#PreAuthorize("hasAuthority('ROLE_ADMIN')")
#RequestMapping(value = "/test", method = RequestMethod.GET)
String test() {
return "Hello";
}
}
Using spring security is safe, as the user is always validated before access is granted . Even while using Oath2 the key generated is after validating the user login and the key can be used to validate every request to the controller by passing it in the header or using it in the rest template.
Another way of isolating your rest endpoints is by using the load balancer (or ngnix or anything) to block requests to these endpoints from outside your domain.

Refresh springboot configuration dynamically

Is there any way to refresh springboot configuration as soon as we change .properties file?
I came across spring-cloud-config and many articles/blogs suggested to use this for a distributed environment. I have many deployments of my springboot application but they are not related or dependent on one another. I also looked at few solutions where they suggested providing rest endpoints to refresh configs manually without restarting application. But I want to refresh configuration dynamically whenever I change .properties file without manual intervention.
Any guide/suggestion is much appreciated.
Can you just use the Spring Cloud Config "Server" and have it signal to your Spring Cloud client that the properties file changed. See this example:
https://spring.io/guides/gs/centralized-configuration/
Under the covers, it is doing a poll of the underlying resource and then broadcasts it to your client:
#Scheduled(fixedRateString = "${spring.cloud.config.server.monitor.fixedDelay:5000}")
public void poll() {
for (File file : filesFromEvents()) {
this.endpoint.notifyByPath(new HttpHeaders(), Collections
.<String, Object>singletonMap("path", file.getAbsolutePath()));
}
}
If you don't want to use the config server, in your own code, you could use a similar scheduled annotation and monitor your properties file:
#Component
public class MyRefresher {
#Autowired
private ContextRefresher contextRefresher;
#Scheduled(fixedDelay=5000)
public void myRefresher() {
// Code here could potentially look at the properties file
// to see if it changed, and conditionally call the next line...
contextRefresher.refresh();
}
}

Spring Cloud Task - launch task from maven repository in docker container

I learn Spring Cloud Task and I write simple application that is divided into 3 services. First is a TaskApplication that have only main() and implements CommandLineRunner, second is a TaskIntakeApplication that receives request and send them to RabbitMQ, third service is an TaskLauncherApplication that receives messages from RabbitMQ and runs the task with received parameters.
#Component
#EnableBinding(Source.class)
public class TaskProcessor {
#Autowired
private Source source;
public void publishRequest(String arguments) {
final String url = "maven://groupId:artifatcId:jar:version";
final List<String> args = Arrays.asList(arguments.split(","));
final TaskLaunchRequest request = new TaskLaunchRequest(url, args, null, null, "TaskApplication");
final GenericMessage<TaskLaunchRequest> message = new GenericMessage<>(request);
source.output().send(message);
}
}
And as you can see I call my built artifact by giving maven url but I wonder how can I call artifact from another docker container?
If you intend to launch a task application from an upstream event (e.g., a new file event; a new DB record event; a new message in Rabbit event, etc.,), you'd simply use the respective out-of-the-box applications and then launch the task via the Task Launcher.
Follow this example on how the 3-steps are orchestrated via SCDF's DSL.
Perhaps you could consider reusing the existing apps instead of reinventing them unless you have got a completely different requirement and that these apps cannot meet it. I'd suggest trying to get the example mentioned above working locally before you consider extending the behavior.

Best way to handle Content Provider failures in Java Spring Application

I have Spring Web Application, which invokes content provider for some data. Its becoming common issue that content provider service is failing and app is becoming unresponsive. What would be best approach or design to check that content provider service is up or down at application level and handle it appropriately.
You can use circuit breaker pattern and Hystrix library.
It will monitor the method annotated with #HystrixCommand and if the failures amount to a certain threshold, it will start redirecting the calls to a fallbackMethod, allowing the continuation of service, and leaving you time to recover from failure.
A simple snippet that shows it in action is as follows:
#Service
public class BookService {
...
#HystrixCommand(fallbackMethod = "reliable")
public String readingList() {
...
}
public String reliable() {
...
}
}

Resources