Spring Boot how to replace string in Springboot Application Class - spring

my main file looks as follows.
#SpringBootApplication
#OpenAPIDefinition(info = #Info(title = "Test", version = "0.1"))
#SecurityScheme(
name = "security_auth", type = SecuritySchemeType.OAUTH2, in = SecuritySchemeIn.HEADER,
flows = #OAuthFlows(implicit = #OAuthFlow(
authorizationUrl = "http://localhost:8080/auth/realms/master/protocol/openid-connect/auth",
tokenUrl = "http://localhost:8080/auth/realms/master/protocol/openid-connect/token",
scopes = {
#OAuthScope(name = "read"),
#OAuthScope(name = "write")
}
))
)
#EnableScheduling
public class TestApplication {
public static void main(String[] args) {SpringApplication.run(TestApplication.class, args);}
}
Is there a way to set the authorizationUrl and tokenUrl by env var ( application.properties)?
The required parameter is String, so I cannot use #Value to inject the value.

The following should do the trick
authorizationUrl = "${your.custom.path}",
and obviously in your application.propperties
your.custom.path=http://localhost:8080/auth/realms/master/protocol/openid-connect/auth

Related

WebFlux API-Layer Test returns 404

I'm trying to get started with Spring WebFlux with Spring Boot 3.0
I'm Building a Person API with an open api generator.
The Application runs and gives the expected results when it is tested manually.
But I'm not able to get the API layer unit tested.
This is my Test Class
#WebFluxTest(controllers = {PersonApiController.class})
#ExtendWith(SpringExtension.class)
#ContextConfiguration(classes = {PersonMapperImpl.class, H2PersonRepository.class, PersonRepository.class})
#DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
class PersonRouterTest {
#MockBean
private PersonService personService;
#Autowired
private WebTestClient client;
#ParameterizedTest
#CsvSource({"1234, Max Mustermann", "5678, Erika Musterfrau"})
void retrieve_a_name(String id, String name) {
when(personService.getPersonDataByID(1234)).thenReturn(Mono.just(new PersonData(1234, "Max Mustermann")));
when(personService.getPersonDataByID(5678)).thenReturn(Mono.just(new PersonData(5678, "Erika Musterfrau")));
client.get()
.uri(uriBuilder -> uriBuilder
.path("/persons/{id}")
.build(id))
.accept(MediaType.ALL)
.exchange()
.expectStatus().isOk()
.expectHeader().contentType(MediaType.APPLICATION_JSON)
.expectBody()
.jsonPath("$.name").isEqualTo(name);
}
This is my Controller Class
#Generated(value = "org.openapitools.codegen.languages.SpringCodegen", date = "2022-12-
09T09:14:36.692713900+01:00[Europe/Vienna]")
#Controller
#RequestMapping("${openapi.openAPIDefinition.base-path:}")
public class PersonApiController implements PersonApi {
private final PersonApiDelegate delegate;
public PersonApiController(#Autowired(required = false) PersonApiDelegate delegate) {
this.delegate = Optional.ofNullable(delegate).orElse(new PersonApiDelegate() {});
}
#Override
public PersonApiDelegate getDelegate() {
return delegate;
}
}
The API interface:
#Tag(
name = "Person",
description = "the Person API"
)
public interface PersonApi {
default PersonApiDelegate getDelegate() {
return new PersonApiDelegate() {
};
}
#Operation(
operationId = "findPersonById",
summary = "Find Person by ID",
tags = {"Person"},
responses = {#ApiResponse(
responseCode = "200",
description = "successful operation",
content = {#Content(
mediaType = "application/json",
schema = #Schema(
implementation = PersonData.class
)
)}
)}
)
#RequestMapping(
method = {RequestMethod.GET},
value = {"/persons/{id}"},
produces = {"application/json"}
)
default Mono<ResponseEntity<PersonData>> findPersonById(#Parameter(name = "id",description = "Person ID",required = true) #PathVariable("id") Integer id, #Parameter(hidden = true) final ServerWebExchange exchange) {
return this.getDelegate().findPersonById(id, exchange);
}
#Operation(
operationId = "savePerson",
summary = "Creates a new Person",
tags = {"Person"},
responses = {#ApiResponse(
responseCode = "200",
description = "successful operatoin",
content = {#Content(
mediaType = "application/json",
schema = #Schema(
implementation = PersonData.class
)
)}
)}
)
#RequestMapping(
method = {RequestMethod.POST},
value = {"/persons"},
produces = {"application/json"},
consumes = {"application/json"}
)
default Mono<ResponseEntity<PersonData>> savePerson(#Parameter(name = "PersonData",description = "") #RequestBody(required = false) Mono<PersonData> personData, #Parameter(hidden = true) final ServerWebExchange exchange) {
return this.getDelegate().savePerson(personData, exchange);
}
}
and finally my delegate impl:
#Service
public class PersonDelegateImpl implements PersonApiDelegate {
public static final Mono<ResponseEntity<?>> RESPONSE_ENTITY_MONO = Mono.just(ResponseEntity.notFound().build());
private final PersonService service;
private final PersonMapper mapper;
public PersonDelegateImpl(PersonService service, PersonMapper mapper) {
this.service = service;
this.mapper = mapper;
}
public static <T> Mono<ResponseEntity<T>> toResponseEntity(Mono<T> mono) {
return mono.flatMap(t -> Mono.just(ResponseEntity.ok(t)))
.onErrorResume(t -> Mono.just(ResponseEntity.internalServerError().build()));
}
#Override
public Mono<ResponseEntity<PersonData>> findPersonById(Integer id, ServerWebExchange exchange) {
Mono<com.ebcont.talenttoolbackend.person.PersonData> personDataByID = service.getPersonDataByID(id);
return toResponseEntity(personDataByID.map(mapper::map));
}
#Override
public Mono<ResponseEntity<PersonData>> savePerson(Mono<PersonData> personData, ServerWebExchange exchange) {
return PersonApiDelegate.super.savePerson(personData, exchange);
If I run the test class I always get:
< 404 NOT_FOUND Not Found
< Content-Type: [application/json]
< Content-Length: [139]
{"timestamp":"2022-12-09T08:45:41.278+00:00","path":"/persons/1234","status":404,"error":"Not Found","message":null,"requestId":"4805b8b8"}
I have tried to change the Context Configuration but I did not get it to work.
I found the Problem, changing the Test Config to :
#WebFluxTest
#ExtendWith(SpringExtension.class)
#ContextConfiguration(classes = {PersonMapperImpl.class, H2PersonRepository.class, PersonRepository.class, PersonApiController.class, PersonDelegateImpl.class})
#DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
Solved my Problem.
The Controller bean was not recognized. I had to add PersonApiCrontroller and PersonDelegateImpl to the Context Config. i then removed the PersonApiController from the #WebFluxTest annotation.

NullPointerException : JUnit test for Repository

Is it correct to write JUnit test case for Repository like this? Also while running it , Iam getting NullPointerException at line Mockito.when...
here is my test class:
#ContextConfiguration(locations = { "classpath*:resources/invoices-context.xml",
"classpath*:resources/invoices-int-schema.xml" })
public class RoomRepositoryTest {
#Autowired
RoomRepository roomRepository;
private RoomEntity roomEntity;
#Test
public void findRommByDateTest() throws ParseException {
String startDate = "27-07-2020";
sDate = new SimpleDateFormat("dd-mm-yyyy").parse(startDate);
String endDate = "28-07-2020";
eDate = new SimpleDateFormat("dd-mm-yyyy").parse(endDate);
String roomType = "SINGLE";
roomEntity = new RoomEntity();
roomEntity.setRoomId(1);
roomEntity.setRoomPrice(6000);
roomEntity.setRoomStatus("AVAILABLE");
roomEntity.setRoomType("SINGLE");
Mockito.when(
roomRepository.findRoomByDate(Mockito.any(Date.class), Mockito.any(Date.class), Mockito.anyString()))
.thenReturn(roomEntity.getRoomId());
int id = roomRepository.findRoomByDate(Mockito.any(Date.class), Mockito.any(Date.class), Mockito.anyString());
assertEquals(1, id);
}
}
Instead of mocking the database fetch function, you can just use the embedded database setup with some annotations. It helps us to test the query efficiently. If you are using an in-memory database(embedded) first you have to add (save) entry in the table. Then your query function should fetch the data. With the help of this you can easily debug the null pointer exceptions.
Eg:
#SpringBootTest
#AutoConfigureTestDatabase
#ContextConfiguration(locations = { "classpath*:resources/invoices-context.xml",
"classpath*:resources/invoices-int-schema.xml" })
public class RoomRepositoryTest {
#Autowired
RoomRepository roomRepository;
private RoomEntity roomEntity;
#Test
public void findRommByDateTest() throws ParseException {
String startDate = "27-07-2020";
sDate = new SimpleDateFormat("dd-mm-yyyy").parse(startDate);
String endDate = "28-07-2020";
eDate = new SimpleDateFormat("dd-mm-yyyy").parse(endDate);
String roomType = "SINGLE";
roomEntity = new RoomEntity();
roomEntity.setRoomId(1);
roomEntity.setRoomPrice(6000);
roomEntity.setRoomStatus("AVAILABLE");
roomEntity.setRoomType("SINGLE");
//adding data for testing
roomRepository.save(roomEntity)
//test the actual function
int id = roomRepository.findRoomByDate(sDate,eDate);
assertEquals(1, id);
}

The resource identified by this request is able to generate responses only with features incompatible with the "accept" directive

I want to make a rest webservice call :
#RestController
#RequestMapping("stock")
public class StockController {
#Autowired
private StockService stockService;
#GetMapping(value = "/TOM", produces = "application/json")
public JsonModel getByLocAndItm(#RequestParam(required=false) String LOC, #RequestParam(required=false) String ITM) {
JsonModel jsonModel = new JsonModel();
List<com.java.oxalys.beans.Stock> stock = stockService.getByLocAndItm(LOC.split("|"), null);
jsonModel.setDatas(stock);
return jsonModel;
}
}
service :
#Service
public class StockServiceImpl implements StockService {
#Autowired
private StockDao stockDao;
#Override
public List<com.java.oxalys.beans.Stock> getByLocAndItm(String[] locs, String[] itms) {
return stockDao.getByLocAndItm(locs, itms);
}
}
DAO :
#Repository
public class StockDaoImpl implements StockDao {
#Override
public List<Stock> getByLocAndItm(String[] locs, String[] itms) {
List<Stock> ret = new ArrayList<Stock>();
String where = "";
String where_locs = "", sep_locs = "";
for(String loc : locs) {
where_locs += sep_locs + " s.LOC_0 = '" + loc + "'";
sep_locs = " or ";
}
where_locs = "(" + where_locs + ")";
where = where_locs;
Stock tmp = new Stock();
tmp.setLoc("eto");
tmp.setItmoxa(where);
ret.add(tmp);
return ret;
}
}
At runtime with postman : localhost:8080/Oxalys_WS/stock/TOM?LOC=BOQSCM171L then I get error The resource identified by this request is able to generate responses only with features incompatible with the "accept" directive present in the request header
So what is wrong ?

how to add app engine bucket's urls to database java

but this code is working fine but only returns app engine bucket's uploaded files url? any idea of how to add the url into the database?
#RestController
#RequestMapping("/api")
public class CloudStorageHelper {
Credentials credentials = GoogleCredentials.fromStream(new FileInputStream("C:\\Users\\sachinthah\\Downloads\\MCQ project -1f959c1fc3a4.json"));
Storage storage = StorageOptions.newBuilder().setCredentials(credentials).build().getService();
public CloudStorageHelper() throws IOException {
}
#SuppressWarnings("deprecation")
#RequestMapping(method = RequestMethod.POST, value = "/imageUpload112")
public String uploadFile(#RequestParam("fileseee")MultipartFile fileStream)
throws IOException, ServletException {
String bucketName = "mcqimages";
checkFileExtension(fileStream.getName());
DateTimeFormatter dtf = DateTimeFormat.forPattern("-YYYY-MM-dd-HHmmssSSS");
DateTime dt = DateTime.now(DateTimeZone.UTC);
String dtString = dt.toString(dtf);
String fileName = fileStream.getOriginalFilename() ;
BlobInfo blobInfo =
storage.create(
BlobInfo
.newBuilder(bucketName, fileName)
.setAcl(new ArrayList<>(Arrays.asList(Acl.of(User.ofAllUsers(), Role.READER))))
.build(),
fileStream.getInputStream()
);
System.out.println(blobInfo.getMediaLink());
return blobInfo.getMediaLink()+",";
}

Resource not invoked after Jersery Request Filter

I have a two SpringServlets defined, one of which directs to a custom filter
#WebServlet(urlPatterns = { "/" }, initParams = {
#WebInitParam(name = "com.sun.jersey.config.property.packages", value = "com.x.y.resource"),
#WebInitParam(name = "com.sun.jersey.api.json.POJOMappingFeature", value = "true") })
public class JerseyServlet extends SpringServlet
{
}
#WebServlet(name = "secure", urlPatterns = "/secure/*", initParams = {
#WebInitParam(name = "com.sun.jersey.config.property.packages", value = "com.x.y.resource"),
#WebInitParam(name = "com.sun.jersey.spi.container.ContainerRequestFilters", value = "com.x.y.resource.OAuthFilter"),
#WebInitParam(name = "com.sun.jersey.api.json.POJOMappingFeature", value = "true") })
public class JerseySecureServlet extends SpringServlet
{
}
The idea being that any URLs that contain "/secure/" are directed to the OAuthFilter to validate the request by the OAuth headers. All other URLs are just handled normally.
For any request sent to a URL not containing "/secure/", the appropriate JAX-RS resource class is invoked correctly. However, for URLs containing "/secure/" the OAuthFilter is invoked correctly, but the JAX-RS annotated Resource class is never invoked afterwards.
Here is an example secure resource
#Component
#Scope("request")
#Path("/secure/example")
public class SecureResource
{
#GET
...
}
and here is the OAuthFilter
#Provider
#Component
public class OAuthFilter implements ContainerRequestFilter
{
public static final String AUTHORIZED_USER = "authorized_user";
#Autowired
AccessTokenService accessTokenService;
#Autowired
UserService userService;
#Context
HttpServletRequest httpRequest;
#Override
public ContainerRequest filter(ContainerRequest containerRequest)
{
OAuthServerRequest request = new OAuthServerRequest(containerRequest);
OAuthParameters params = new OAuthParameters();
params.readRequest(request);
String accessToken = params.getToken();
if (accessToken == null)
{
throw new WebApplicationException(Status.UNAUTHORIZED);
}
String userId = accessTokenService.getUserIdForToken(accessToken);
if (userId == null)
{
throw new WebApplicationException(Status.UNAUTHORIZED);
}
User user = userService.get(userId);
if (user == null)
{
throw new WebApplicationException(Status.NOT_FOUND);
}
httpRequest.setAttribute(AUTHORIZED_USER, user);
return containerRequest;
}
}
It looks like once the JerseySecureServlet with the "/secure/*" mapping is selected and the OAuthFilter is invoked the baseURI is "http:/ip:port/context/secure" and the path is simply "/example", and no Resource corresponds to this path, so nothing is invoked. What should I be doing instead to only apply this filter to URLs that contain "/secure/"?
I have solved the problem, but I am not 100% sure if my solution is the correct way to do it. I have changed the annotation on the filtered serlvet to be #WebFilter, giving me
#WebServlet(urlPatterns = { "/*" }, initParams = {
#WebInitParam(name = "com.sun.jersey.config.property.packages", value = "com.x.y.resource"),
#WebInitParam(name = "com.sun.jersey.api.json.POJOMappingFeature", value = "true") })
public class JerseyServlet extends SpringServlet
{
}
#WebFilter(urlPatterns = "/secure/*", initParams = {
#WebInitParam(name = "com.sun.jersey.config.property.packages", value = "com.x.y.resource"),
#WebInitParam(name = "com.sun.jersey.spi.container.ContainerRequestFilters", value = "com.x.y.resource.OAuthFilter"),
#WebInitParam(name = "com.sun.jersey.api.json.POJOMappingFeature", value = "true") })
public class JerseySecureFilter extends SpringServlet
{
}
and this works. A better solution will be accepted over this one.

Resources