How to run this with out spring boot - java

I am new to spring and maven, i do have this app which is referring from, https://spring.io/guides/gs/rest-service/
I am using spring + maven.
I need to get the output into a simple html via tomcat, currently it is using embedded Apache Tomcat 7.
package hello;
public class Greeting {
private final long id;
private final String content;
public Greeting(long id, String content) {
this.id = id;
this.content = content;
}
public long getId() {
return id;
}
public String getContent() {
return content;
}
}
package hello;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
#RequestMapping("/greeting")
public Greeting greeting(#RequestParam(value="name", defaultValue="World") String name) {
return new Greeting(counter.incrementAndGet(),
String.format(template, name));
}
}
This is the main which uses spring boot, to run in embedded Apache.
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Can someone help me with this! What i need is simple web service without embedded tomcat. just need normal tomcat deploying.
pom.xml is as bellow.
<?xml version="1.0" encoding="UTF-8"?>
<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>org.springframework</groupId>
<artifactId>gs-rest-service</artifactId>
<version>0.1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.2.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-releases</id>
<url>https://repo.spring.io/libs-release</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-releases</id>
<url>https://repo.spring.io/libs-release</url>
</pluginRepository>
</pluginRepositories>
</project>

Perfect Solution and code to your Question
SpringBoot contains Embedded Tomcat, Hence there is no special configuration required in your POM.xml
Your POM.xml should like this below code. I have used bootsample as an artifact and hence rest are all same.
<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>com.yourcompany.app</groupId>
<artifactId>bootsample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.2.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<finalName>bootsample</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>${start-class}</mainClass>
<layout>ZIP</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-releases</id>
<url>https://repo.spring.io/libs-release</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-releases</id>
<url>https://repo.spring.io/libs-release</url>
</pluginRepository>
</pluginRepositories>
</project>
</project>
Your Greeting Domain Object.
/**
*
*/
import org.springframework.stereotype.Component;
/**
* #author Praveen
*
*/
#Component
public class Greeting {
private final long id;
private final String content;
public Greeting(long id, String content) {
this.id = id;
this.content = content;
}
public long getId() {
return id;
}
public String getContent() {
return content;
}
}
Your Controller, Before careful you have use #ResponseBody annotation, else you will get circularpath ViewResolver Exception, because SpringBoot sets default viewResolver. This #ResponseBody annotation will skip your ViewResolver problems.
/**
*
*/
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* #author Praveen
*
*/
#Controller
#EnableAutoConfiguration
#ResponseBody
//#ComponentScan
public class SimpleController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
#RequestMapping("/greeting")
public Greeting greeting(#RequestParam(value="name", defaultValue="World") String name) {
return new Greeting(counter.incrementAndGet(),
String.format(template, name));
}
public static void main(String[] args) throws Exception {
SpringApplication.run(SimpleController.class, args);
}
}
Please use the Maven Goals as indicated in below figure.
Your maven goals should be mvn clean package spring-boot:run -e
Once you execute this, your embedded tomcat will run and you can find your successful output.
Successful Log
Additionally you can refer this link Spring-boot reference documentation. for your WAR/JAR creation questions.

Add This to your POM
<packaging>war</packaging>
and do mvn install or mvn package
You will see in your target folder the artifact ending with xxx.war.original. That one can be deployed straight into Tomcat.
edit:- Update as per comments below. Following changes needs to be made as well.
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
Refer doc for more details as cited in the comments section.

Related

Endpoint specifications ("paths" field) not getting generated in the Swagger API specification file generated by swagger-maven-plugin

I have a simple swagger annotated API (a GET and a POST method). I'm trying to generate the Swagger API specification file using the swagger-maven-plugin. The Swagger API specifications file is getting created but the problem is that it only has the API meta data in it and no info about the endpoints is getting generated i.e. the "paths" field is not getting generated.
My pom.xml :
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>rest-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>rest-api</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.github.kongchen</groupId>
<artifactId>swagger-maven-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<apiSources>
<apiSource>
<springmvc>true</springmvc>
<locations>com.example.restapi.DriverController</locations>
<schemes>http</schemes>
<host>localhost:8080</host>
<basePath>/api</basePath>
<info>
<title>Swagger Maven Plugin Sample</title>
<version>v1</version>
<description>This is a sample for swagger-maven-plugin</description>
<contact>
<name>My name</name>
</contact>
<license>
<url>http://www.apache.org/licenses/LICENSE-2.0.html</url>
<name>Apache 2.0</name>
</license>
</info>
<outputPath>${basedir}/generated/document.html</outputPath>
<outputFormats>json,yaml</outputFormats>
<swaggerDirectory>generated/swagger-ui</swaggerDirectory>
</apiSource>
</apiSources>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Driver.java class :
package com.example.restapi;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
#ApiModel(description = "This is the driver model")
public class Driver {
#ApiModelProperty(notes = "The id of the driver")
private int driverId;
#ApiModelProperty(notes = "The name of the driver")
private String driverName;
#ApiModelProperty(notes = "The name of the car")
private String carName;
public Driver(int driverId, String driverName, String carName) {
this.driverId = driverId;
this.driverName = driverName;
this.carName = carName;
}
}
DriverController.java class :
package com.example.restapi;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
#RequestMapping("/api")
#RestController
#Api(value = "Driver API Rest Controller")
public class DriverController {
private static List<Driver> drivers = new ArrayList<Driver>();
static{
drivers.add(new Driver(1,"Name1","VW"));
drivers.add(new Driver(2,"Name2","Honda"));
drivers.add(new Driver(3,"Name3","Audi"));
}
#GetMapping("/drivers")
#ApiOperation(value="Get list of all available drivers", response=List.class)
#ApiResponses(value={
#ApiResponse(code=200, message="Success, OK"),
#ApiResponse(code=404, message="Not found")
})
public List<Driver> getDrivers(){
return drivers;
}
#PostMapping("/driver")
#ApiOperation(value="Add a new driver to the list of all available drivers", response=Driver.class)
#ApiResponses(value={
#ApiResponse(code=200, message="Success, OK"),
#ApiResponse(code=404, message="Not found")
})
public List<Driver> createDriver(#RequestBody Driver driver){
drivers.add(driver);
return drivers;
}
}
SwaggerConfig.java class :
package com.example.restapi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
//import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
//import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
#Configuration
#EnableSwagger2
public class SwaggerConfig {
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.restapi"))
.paths(PathSelectors.any())
.build();
}
}
The API specifications file generated by swagger-maven-plugin is (on running mvn compile):
{
"swagger":"2.8",
"info":{
"description" : "This is a sample for swagger-maven-plugin",
"version":"v1",
"title":"Swagger Maven Plugin Sample",
"contact":{
"name":"My name"
},
"license":{
"name":"Apache 2.0",
"url":"http://www.apache.org/license/LICENSE-2.0.html"
},
"host":"localhost:8080",
"basePath":"/api",
"schemes" :["http","https"]
}
}
As you can notice there is no information about the endpoints in the above specification. Please help.
Thanks in advance!
I was facing the same issue, try using plugin version 3.1.7 instead of 3.1.1
and the also change the locations tag, try
<locations>
<location>com.example.restapi.DriverController</location>
</locations>
It worked for me after making these changes.

Here I am trying to do a simple CRUD operation using micronaut microservices. But getting some errors

I am trying to do some crud operation using micornaut microservices in java.
But getting this error, Please if anyone can help me out.
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.625 s <<< FAILURE! - in micronautDataAcess.MicronautDataAcessTest
[ERROR] micronautDataAcess.MicronautDataAcessTest Time elapsed: 0.623 s <<< ERROR!
java.lang.RuntimeException: Failed to load a service: Unexpected error loading bean definition [micronautDataAcess.$Repository.StudentRepository$Interce
pted$Definition]: failed to access class micronautDataAcess.Repository.StudentRepository$Intercepted from class micronautDataAcess.$Repository.StudentRe
pository$Intercepted$Definition$Reference (micronautDataAcess.Repository.StudentRepository$Intercepted and micronautDataAcess.$Repository.StudentReposit
ory$Intercepted$Definition$Reference are in unnamed module of loader 'app')
Caused by: io.micronaut.context.exceptions.BeanContextException: Unexpected error loading bean definition [micronautDataAcess.$Repository.StudentReposit
ory$Intercepted$Definition]: failed to access class micronautDataAcess.Repository.StudentRepository$Intercepted from class micronautDataAcess.$Repositor
y.StudentRepository$Intercepted$Definition$Reference (micronautDataAcess.Repository.StudentRepository$Intercepted and micronautDataAcess.$Repository.Stu
dentRepository$Intercepted$Definition$Reference are in unnamed module of loader 'app')
Caused by: java.lang.IllegalAccessError: failed to access class micronautDataAcess.Repository.StudentRepository$Intercepted from class micronautDataAces
s.$Repository.StudentRepository$Intercepted$Definition$Reference (micronautDataAcess.Repository.StudentRepository$Intercepted and micronautDataAcess.$Re
pository.StudentRepository$Intercepted$Definition$Reference are in unnamed module of loader 'app')
POM FILE -
<?xml version="1.0" encoding="UTF-8"?>
<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>micronautDataAcess</groupId>
<artifactId>micronautDataAcess</artifactId>
<version>0.1</version>
<packaging>${packaging}</packaging>
<parent>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-parent</artifactId>
<version>3.1.3</version>
</parent>
<properties>
<packaging>jar</packaging>
<jdk.version>1.8</jdk.version>
<!-- If you are building with JDK 9 or higher, you can uncomment the lines below to set the release version -->
<!-- <release.version>8</release.version> -->
<micronaut.version>3.1.3</micronaut.version>
<exec.mainClass>micronautDataAcess.Application</exec.mainClass>
<micronaut.runtime>netty</micronaut.runtime>
</properties>
<repositories>
<repository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-inject</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-validation</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micronaut.test</groupId>
<artifactId>micronaut-test-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-client</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-server-netty</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-runtime</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.micronaut.data</groupId>
<artifactId>micronaut-data-jdbc</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut.sql</groupId>
<artifactId>micronaut-jdbc-hikari</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.micronaut.data</groupId>
<artifactId>micronaut-data-hibernate-jpa</artifactId>
<version>3.2.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.micronaut.build</groupId>
<artifactId>micronaut-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<!-- Uncomment to enable incremental compilation -->
<!-- <useIncrementalCompilation>false</useIncrementalCompilation> -->
<annotationProcessorPaths combine.children="append">
<path>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-validation</artifactId>
<version>${micronaut.version}</version>
</path>
</annotationProcessorPaths>
<compilerArgs>
<arg>-Amicronaut.processing.group=micronautDataAcess</arg>
<arg>-Amicronaut.processing.module=micronautDataAcess</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
</pluginRepository>
<pluginRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>
Controller File -
package micronautDataAcess.Controller;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.annotation.*;
import jakarta.inject.Inject;
import micronautDataAcess.Model.StudentModel;
import micronautDataAcess.Services.StudentServiceInterface;
import java.util.Optional;
#Controller("/crud")
public class StudentController {
#Inject
StudentServiceInterface studentServiceInterface;
/*Endpoint for the post method */
#Post(value = "/add")
#Consumes(value = "application/json")
public HttpResponse save(#Body StudentModel crudDemoModel){
StudentModel savedCrudDemoModel = studentServiceInterface.save(crudDemoModel);
return HttpResponse.created(savedCrudDemoModel);
}
/* Endpoint for the finding */
#Get(value = "/find")
#Produces(value = "application/json")
public HttpResponse findById(#NonNull Integer sid){
Optional<StudentModel> foundModelObject = studentServiceInterface.findById(sid);
if(foundModelObject.isPresent()){
return HttpResponse.ok(foundModelObject);
}
return HttpResponse.badRequest("\'Error\':\'Id provied not found in the DB'" );
}
}
Model -
package micronautDataAcess.Model;
import javax.persistence.*;
#Entity
#Table(name = "dummystudent")
public class StudentModel {
/*All the column data*/
/* Student id */
#Id
Integer sid;
/* Student name */
#Column(name = "name", nullable = false, unique = false)
String name;
/* Getter method for sid */
public Integer getSid() {
return sid;
}
/* Setter method for the student id */
public void setSid(int sid) {
this.sid = sid;
}
/* Getter method for student name */
public String getName() {
return name;
}
/* Setter method for student name */
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return "StudentModel {" +
"sid" + sid +
"name" + name + "}";
}
}
Repository -
package micronautDataAcess.Repository;
import io.micronaut.data.annotation.Repository;
import io.micronaut.data.repository.CrudRepository;
import micronautDataAcess.Model.StudentModel;
import java.util.Optional;
#Repository
/* Curd repository -- will accept the 2 parameters
1. object, char, string etc.
2. Will accept the Integer -- that is no primitive data type.
Here we are passing studentModel - object and Integer
*/
public interface StudentRepository extends CrudRepository<StudentModel, Integer> {
/* Save method will return the student object on save*/
StudentModel save(StudentModel studentModel);
/* Optional - if the entity is not found then it will return null otherwise it will return student
entity containing all the student column data.
*/
Optional<StudentModel> findById(Integer sid);
/* Excepted the void method for the delete operation -- */
void deleteById(Integer sid);
}
Services -
Service Interface
package micronautDataAcess.Services;
import micronautDataAcess.Model.StudentModel;
import java.util.Optional;
public interface StudentServiceInterface {
StudentModel save(StudentModel studentModel);
Optional<StudentModel> findById(Integer sid);
void deleteById(Integer sid);
}
Service Implementation
package micronautDataAcess.Services;
import io.micronaut.context.annotation.Bean;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import micronautDataAcess.Model.StudentModel;
import micronautDataAcess.Repository.StudentRepository;
import java.util.Optional;
/*Initialization of Bean and Indicating the Singleton instance */
#Singleton
#Bean
public class StudentServiceImpl implements StudentServiceInterface {
/* Injecting the Student repository here in the Service Implementation */
#Inject
StudentRepository studentRepository;
/*Here we are overriding the StudentModel object that save the method.*/
#Override
public StudentModel save(StudentModel studentModel) {
return studentRepository.save(studentModel);
}
/*Here we are overriding the StudentModel -- findbyid method.*/
#Override
public Optional<StudentModel> findById(Integer sid) {
return studentRepository.findById(sid);
}
/*Here we are overriding the StudentModel -- deleteById.*/
#Override
public void deleteById(Integer sid) {
studentRepository.deleteById(sid);
}
}
Application.yml file
micronaut:
application:
name: micronautDataAcess
datasources:
default:
url: jdbc:mysql://localhost:3306/micronautspractises
user: root
password: ""
driverClassName: com.mysql.cj.jdbc.Driver
dialect: MYSQL
flyway:
datasources:
packages-to-scan: 'StudentModel'
default:
enabled: true
So I have attached all the dependencies and other file used In program. If anyone can suggest a better way to resolve the issue.

Basic Spring based WSSecurity client gets a null response

I've been following this tutorial to learn how to develop a basic spring client and server application using wssecurity (certificates).
The demo works beautifully, but i need to deploy my application on a wildfly server, so i had to change the example a bit in order to avoid the embedded tomcat, the changes are as follows:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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>com.memorynotfound.spring.ws</groupId>
<artifactId>ws-security-certificate-wss4j-security-interceptor</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>SPRING-WS - ${project.artifactId}</name>
<url>http://memorynotfound.com</url>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-security</artifactId>
</dependency>
<dependency>
<groupId>org.apache.ws.security</groupId>
<artifactId>wss4j</artifactId>
<version>1.6.19</version>
</dependency>
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
<version>1.6.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>2.5.0</version>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<sources>
<source>src/main/resources/xsd</source>
</sources>
<generatePackage>com.memorynotfound.beer</generatePackage>
</configuration>
</plugin>
</plugins>
</build>
RunServer.java
package com.memorynotfound.server;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
#SpringBootApplication
public class RunServer extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(RunServer.class);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(applicationClass);
}
private static Class<RunServer> applicationClass = RunServer.class;
}
BeerEndpoint.java
package it.corvallis.soap.endpoint;
import com.memorynotfound.beer.Beer;
import com.memorynotfound.beer.GetBeerRequest;
import com.memorynotfound.beer.GetBeerResponse;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
import org.springframework.ws.soap.server.endpoint.annotation.SoapAction;
#Endpoint
public class BeerEndpoint {
public static final String NAMESPACE_URI = "http://memorynotfound.com/beer";
#PayloadRoot(namespace = NAMESPACE_URI, localPart = "getBeerRequest")
#SoapAction("http://localhost:8080/ws/beers")
#ResponsePayload
public GetBeerResponse getBeer(#RequestPayload GetBeerRequest request) {
GetBeerResponse beerResponse = new GetBeerResponse();
Beer beer = new Beer();
beer.setId(request.getId());
beer.setName("Beer name");
beerResponse.setBeer(beer);
return beerResponse;
}
}
I deployed the server application on my wildfly and i tried to call it using the same client application used in the tutorial. The service seems to answer correctly, the beerResponse object is correctly istantiated, but, as soon as the object is being sent back to the the client, i see it's NULL.
What am i missing?
Thanks in advance
Oh well, next time i'll read better. At the same link of my first post, a guy asked the same question in the comments, here is the solution: add a callBackHandler to the client configuration, and modify the securityInterceptor to use this handler.
SoapClientConfig.java
package com.memorynotfound.client;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.stereotype.Component;
import org.springframework.ws.client.support.interceptor.ClientInterceptor;
import org.springframework.ws.soap.security.wss4j2.Wss4jSecurityInterceptor;
import org.springframework.ws.soap.security.wss4j2.callback.KeyStoreCallbackHandler;
import org.springframework.ws.soap.security.wss4j2.support.CryptoFactoryBean;
import java.io.IOException;
#Configuration
public class SoapClientConfig {
#Bean
public Wss4jSecurityInterceptor securityInterceptor() throws Exception {
Wss4jSecurityInterceptor securityInterceptor = new Wss4jSecurityInterceptor();
// set security actions
securityInterceptor.setSecurementActions("Timestamp Signature Encrypt");
// sign the request
securityInterceptor.setSecurementUsername("client");
securityInterceptor.setSecurementPassword("changeit");
securityInterceptor.setSecurementSignatureCrypto(getCryptoFactoryBean().getObject());
// encrypt the request
securityInterceptor.setSecurementEncryptionUser("server-public");
securityInterceptor.setSecurementEncryptionCrypto(getCryptoFactoryBean().getObject());
securityInterceptor.setSecurementEncryptionParts("{Content}{http://memorynotfound.com/beer}getBeerRequest");
// sign the response
securityInterceptor.setValidationActions("Signature Encrypt");
securityInterceptor.setValidationSignatureCrypto(getCryptoFactoryBean().getObject());
securityInterceptor.setValidationDecryptionCrypto(getCryptoFactoryBean().getObject());
securityInterceptor.setValidationCallbackHandler(securityCallbackHandler());
return securityInterceptor;
}
#Bean
public CryptoFactoryBean getCryptoFactoryBean() throws IOException {
CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();
cryptoFactoryBean.setKeyStorePassword("changeit");
cryptoFactoryBean.setKeyStoreLocation(new ClassPathResource("client.jks"));
return cryptoFactoryBean;
}
#Bean
public Jaxb2Marshaller getMarshaller(){
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("com.memorynotfound.beer");
return marshaller;
}
#Bean
public BeerClient getBeerClient() throws Exception {
BeerClient beerClient = new BeerClient();
beerClient.setMarshaller(getMarshaller());
beerClient.setUnmarshaller(getMarshaller());
beerClient.setDefaultUri("http://localhost:8080/ws/beers");
ClientInterceptor[] interceptors = new ClientInterceptor[]{securityInterceptor()};
beerClient.setInterceptors(interceptors);
return beerClient;
}
#Bean
public KeyStoreCallbackHandler securityCallbackHandler(){
KeyStoreCallbackHandler callbackHandler = new KeyStoreCallbackHandler();
callbackHandler.setPrivateKeyPassword("changeit");
return callbackHandler;
}
}

Programmatic Control over entry-time-to-live in Gemfire Region with ClientRegionShortcut.PROXY

Is it possible to have a ClientCache with ClientRegionShortcut.PROXY along with programmatic control over entry TTL settings (i.e. entries present in the server)? I see the entry expiration ttl settings working fine with ClientRegionShortcut.CACHING_PROXY_HEAP_LRU. In this case I can see the entries getting invalidated in server after the configured timeout in seconds, but that is not the case for ClientRegionShortcut.PROXY settingsIs it NOT possible to dynamically control the entry-ttl settings for a ClientCache? Below code/config works with ClientRegionShortcut.CACHING_PROXY_HEAP_LRU and NOT with ClientRegionShortcut.PROXY.
The Gemfire version is : 9.0.x
The pom looks like below
<?xml version="1.0" encoding="UTF-8"?>
<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>com.springboot.gemfire</groupId>
<artifactId>app</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>MyGemfireProject</name>
<description>Test Concepts project for Spring Boot with Gemfire</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-gemfire</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>0.7.4</version>
</dependency>
<dependency>
<groupId>com.gemstone.gemfire</groupId>
<artifactId>gemfire</artifactId>
<version>8.2.6</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>org.springframework.maven.milestone</id>
<name>Spring Maven Milestone Repository</name>
<url>http://repo.springsource.org/libs-milestone</url>
<snapshots><enabled>false</enabled></snapshots>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
The Gemfire Configuration looks like below:
import java.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;
import org.springframework.data.gemfire.ExpirationActionType;
import org.springframework.data.gemfire.support.GemfireCacheManager;
import com.gemstone.gemfire.cache.AttributesMutator;
import com.gemstone.gemfire.cache.ExpirationAttributes;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.client.ClientCache;
import com.gemstone.gemfire.cache.client.ClientCacheFactory;
import com.gemstone.gemfire.cache.client.ClientRegionFactory;
import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
import com.gemstone.gemfire.pdx.ReflectionBasedAutoSerializer;
/**
* The Class NativeGemfireConfig.
*/
#Configuration
#Profile("local")
public class NativeGemfireConfig {
/** The Constant log. */
private static final Logger log = LoggerFactory.getLogger(NativeGemfireConfig.class);
protected static final String DEFAULT_MANAGER_PORT = "1099";
/** The region name. */
#Value("${spring.gemfire.region.name:test}")
private String regionName;
#Bean
Properties gemfireProperties(#Value("${spring.gemfire.log-level}") String logLevel,
#Value("${spring.gemfire.mcast-port}") String mcastPort,
#Value("${spring.gemfire.jmx-manager}") String jmxManager,
#Value("${spring.gemfire.jmx-manager-start}") String jmxManagerStart,
#Value("${spring.gemfire.username}") String gemfireuser,
#Value("${spring.gemfire.password}") String gemfirepassword) {
Properties gemfireProperties = new Properties();
gemfireProperties.setProperty("name", NativeGemfireConfig.class.getSimpleName());
gemfireProperties.setProperty("mcast-port", mcastPort);
gemfireProperties.setProperty("log-level", logLevel);
gemfireProperties.setProperty("jmx-manager", jmxManager);
gemfireProperties.setProperty("jmx-manager-port", DEFAULT_MANAGER_PORT);
gemfireProperties.setProperty("jmx-manager-start", jmxManagerStart);
gemfireProperties.setProperty("security-username", gemfireuser);
gemfireProperties.setProperty("security-password", gemfirepassword);
gemfireProperties.setProperty("security-client-auth-init",
"com.springboot.gemfire.config.GemFireAuthInitializor.create");
return gemfireProperties;
}
#Bean
#Primary
ReflectionBasedAutoSerializer reflectionBasedAutoSerializer() {
return new ReflectionBasedAutoSerializer("com.springboot.gemfire.model.*");
}
#Bean
#Primary
ClientCacheFactory clientCacheFactory(#Value("${spring.gemfire.host}") String gemFirehost,
#Value("${spring.gemfire.port}") int gemfirePort, Properties gemfireProperties,
ReflectionBasedAutoSerializer reflectionBasedAutoSerializer) {
ClientCacheFactory cachefactory = new ClientCacheFactory(gemfireProperties);
cachefactory.addPoolLocator(gemFirehost, gemfirePort);
cachefactory.setPdxSerializer(reflectionBasedAutoSerializer);
cachefactory.setPdxReadSerialized(false);
cachefactory.setPdxIgnoreUnreadFields(true);
return cachefactory;
}
/**
* Gemfire cache.
*
* #return the client cache
*/
#Bean
#Primary
ClientCache gemfireCache(#Qualifier("gemfireProperties")Properties gemfireProperties,
ClientCacheFactory clientCacheFactory,
#Value("${spring.gemfire.username}") String gemfireuser,
#Value("${spring.gemfire.password}") String gemfirepassword)
{
return
clientCacheFactory
.set("security-username", gemfireuser)
.set("security-password", gemfirepassword)
.set("security-client-auth-init",
"com.springboot.gemfire.config.GemFireAuthInitializor.create")
.create();
}
#Bean
public ExpirationAttributes entryTtlExpirationAttributes(
#Value("${spring.gemfire.region.expiration.entry.ttl.timeout}") int timeout) {
return new ExpirationAttributes(timeout,
ExpirationActionType.INVALIDATE.getExpirationAction());
}
#Bean
#Primary
Region<Object, Object> tokenRegionBean(ClientCache gemfireCache,
#Qualifier("entryTtlExpirationAttributes") ExpirationAttributes expirationAttributes) {
ClientRegionFactory<Object, Object> tokenRegionFactory = gemfireCache
.createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY_HEAP_LRU);
tokenRegionFactory.setStatisticsEnabled(true);
Region<Object, Object> region = tokenRegionFactory.create(regionName);
AttributesMutator<Object, Object> mutator = region.getAttributesMutator();
mutator.setEntryTimeToLive(expirationAttributes);
return region;
}
#Bean
GemfireCacheManager cacheManager(ClientCache gemfireCache) {
GemfireCacheManager cacheManager = new GemfireCacheManager();
cacheManager.setCache(gemfireCache);
return cacheManager;
}
/**
* Gets the region name.
*
* #return the region name
*/
public String getRegionName() {
return regionName;
}
/**
* Sets the region name.
*
* #param regionName
* the new region name
*/
public void setRegionName(final String regionName) {
this.regionName = regionName;
}
}
The application-local.yml relevant entries are
spring:
gemfire:
log-level: config
region:
name: myRegion
expiration:
entry:
ttl:
timeout: 120
host: remote-server
port: port-to-connect
mcast-port: 0
jmx-manager: false
jmx-manager-start: false
username: uname
password: passwd

How to connect from STS(spring tool suite) to database(oracle)

I am new at spring. I am trying to build my first web service, and I would like to connect to a database, get data, and return it as a JSON.
I use the spring example https://spring.io/guides/gs/rest-service and I change it a bit, so I can get a war file.
My server that war file will deploy is Wildfly 8.2.0.
I want to connect to oracle 11g database and run SQL queries. Can you help me?
My code is posted below.
My project format in eclipse
Application.java:
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
Greeting.java:
package hello;
public class Greeting {
private final long id;
private final String content;
public Greeting(long id, String content) {
this.id = id;
this.content = content;
}
public long getId() {
return id;
}
public String getContent() {
return content;
}
}
GreetingController.java:
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
#RequestMapping(value="/greeting",method=RequestMethod.GET)
public List<Greeting> greeting(#RequestParam(value="name", defaultValue="World") String name,
#RequestParam(value="content", defaultValue="World") String content,HttpServletResponse response) {
List<Greeting> list_greet = new ArrayList<Greeting>();
list_greet.add(new Greeting(counter.incrementAndGet(),
String.format(template, name)));
list_greet.add(new Greeting(counter.incrementAndGet(),
String.format(template, content)));
list_greet.add(new Greeting(counter.incrementAndGet(),
String.format(template, name)));
list_greet.add(new Greeting(counter.incrementAndGet(),
String.format(template, name)));
//to have webservice work,beacause cors cut it out.
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
return list_greet;
}
}
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<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>org.springframework</groupId>
<artifactId>gs-rest-service</artifactId>
<version>0.1.0</version>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-releases</id>
<url>https://repo.spring.io/libs-release</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-releases</id>
<url>https://repo.spring.io/libs-release</url>
</pluginRepository>
</pluginRepositories>
</project>
Thanks in advance!
You can use several different ways to archive your objective, for example:
Follow this official doc and use Spring with jpa directly
This one just adapted to spring-boot in combination with official spring jpa example

Categories