How to hide endpoints based on Profiles in Spring Boot and Spring doc? - springdoc

I am working on Spring Boot v2.2.2.RELEASE and SpringDoc UI and Open API Specification OAS3 and I found very related question here: https://github.com/springdoc/springdoc-openapi/issues/201.
I've 4 Profiles say Dev, Stage, UAT and Prod and say I've Student API, Employee API and Department API.
I want for UAT and Prod profiles, I want to hide Department API. How can we do not ?

You can use groups: Declare each of your API in groups.
https://springdoc.org/faq.html#how-can-i-define-multiple-openapi-definitions-in-one-spring-boot-project
And, add the #Profile annotation together with #Bean annotation for the group definition: This will help you display the OpenAPI spec depending on your spring profiles
#Bean
#Profile("!prod")
public GroupedOpenApi actuatorApi() {
return GroupedOpenApi.builder().group("Actuator")
.pathsToMatch("/actuator/**")
.pathsToExclude("/actuator/health/*")
.build();
}

Related

Instrumentation of Mysql Jpa Repository in Spring using AWS X-Ray not working

I am trying to instrument Mysql calls using AWS X-Ray in my spring application. http and s3 instrumentation is working fine.
I have set the property: spring.datasource.jdbc-interceptors=com.amazonaws.xray.sql.mysql.TracingInterceptor
I have included following dependancies in build.gradle
compile 'com.amazonaws:aws-xray-recorder-sdk-spring'
compile("com.amazonaws:aws-xray-recorder-sdk-core")
compile("com.amazonaws:aws-xray-recorder-sdk-aws-sdk")
compile("com.amazonaws:aws-xray-recorder-sdk-aws-sdk-instrumentor")
compile("com.amazonaws:aws-xray-recorder-sdk-apache-http")
compile("com.amazonaws:aws-xray-recorder-sdk-sql-mysql")
dependencyManagement {
imports {
mavenBom('com.amazonaws:aws-xray-recorder-sdk-bom:1.3.1')
}
}
I am using JpaRepositories. I am expecting all my sql queries to get instrumented automatically after above setup is done. I am following amazon doc at this location: https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-java-sqlclients.html
What am I missing?
Update: I can see mysql traces for spring's health endpoint. But jpa calls are still unseen.
Are you constructing the DataSource object using the defined spring.datasource properties in your application.properties?
See this dataSource() method (GitHub) in the RdsWebConfig class which uses the #ConfigurationProperties(prefix = "spring.datasource") annotation in order to pick up the relevant jdbc-interceptors property.
Hope this helps.
James

Best way to use spring for Web and mobile application

I am new to web development. I am planning to create a web service which is going to act as a back end for both web site and mobile application. I want to know if it is possible to use same method to return data in different type.
For example:
If i use http://somewebsite/getdetails.jsp should give me and modelView return type and http://somewebsite/getdetails.json should give the model in json format.
I don't want to create two different controller to handle this.
If there is any other better way also please share your comments.
I am open for alternative solutions too
Spring 4.0 / Spring Boot enables you to achieve this quite easily. I am currently developing web-service (API) for mobile and backend for browser based clients and I just simply split API for mobile under URL #RequestMapping("/api"). In addition, Spring allows you to easily implement RESTful url based application. I recommend you to have two different controllers for API and Web MVC because it ensures complete separation between two different logics. E.g.
Would you really like to implement something like following?
#SuppressWarnings("unchecked")
public Map<Object, Object> test(#RequestParam(value="mobileyes") boolean mobile){
if(mobile){
Map<Object, Object> m = new HashMap<Object, Object>();
m.put("test", "test")
return m;
} else {
ModelAndView mv = new ModelAndView();
mv.addObject("test", "test");
mv.setViewName("test");
return (Map<Object, Object>) mv;
}
}
Above example might work, but ugly and will certainly cause maintenance disaster in near future.
This is my overall structure of Spring MVC using Spring Boot :
Ordinary URL accessed by desktop based and mobile based browsers
These controllers use
#Controller annotation because it doesn't automatically enables #ResponseBody
www.mybusinesscard.com.au/ -> Index
//Displaying all businesscards
www.mybusinesscard.com.au/businesscards -> view all
//For saving from form
www.mybusinesscard.com.au/businesscard/save -> save a card
Following controller examples are for mobile API:
Following controllers use #RestController annotation to automatically enable requirements necessary for WebServices. E.g: #ResponseBody
www.mybusinesscard.com.au/api -> Index
//Displaying all businesscards
www.mybusinesscard.com.au/api/businesscards -> view all
//For saving from form
www.mybusinesscard.com.au/api/businesscard/save -> save a card

ASP.NET Web API Repository Pattern Service Layer (Business Logic)

I just finish to implement Repository Pattern & Unit of Work using Ninject Dependency Injection into my asp.net web api project.
Im using Entity Framework as my ORM.
I have the following soluction structure (projects):
Web Application (asp.net web api)
Data (DBContext, Repositories)
Interfaces (IRepository, etc)
Model (POCO Classes from DB)
So for example my PersonRepository (Data project):
public class PersonsRepository : EFRepository<Person>, IPersonsRepository
{
public PersonsRepository(DbContext context) : base(context) { }
public IQueryable<Person> GetByAge(int age)
{
return DbSet.FirstOrDefault(ps => ps.age == age);
}
public void Delete(int personId, int age)
{
// Here I want to validate some stuff before deleting
// Business Rules need to be here!!
var attendance = new Attendance {PersonId = personId, Age = age};
Delete(attendance);
}
}
So my question is if its correct to implement all the business logic inside my Repository Methods? and also what is the best way to return a message or validation in case I need to.
Thanks and appreciate any help!
There should be a new layer between Data and Web called Business. Web will reference Business layer only and Business layer will reference Data layer only. So the Business layer before or after calling the Data layer can implement all its validation and business logic.
No, it isn't. The repository implementation belongs to persistence (DAL). Repository is concerned with 'converting' business objects to/from whatever form used to store them into the database. It isn't its responsibility to care about business logic. Business logic stays in the business layer, in the domain.
Business logic is contained by domain objects and services. It never gets outside the business layer, not in UI (controllers) not in DAL (repositories, EF etc).
The repository implementation you're using is incorrect, an anti-pattern, as it defeats the purpose of a repository: to decouple the business layer from the persistence details (EF is an implementation detail). The repository's interface should never expose details like IQueryable or EF entities. It should 'know' only about business objects.
Your solution structure makes little sense to me: all interfaces you're using should be in the layer they belong to(repository interface is part of business layer, that's why it shouldn't know about EF). The Model, based on your description seems to be the persistence model (it should be part of Data).
You want a Business(Domain) layer where Model really means business model. Not to be confused with persistence model(used by EF), view model(used by a View) or the M from MVC (used by Controllers) :) . The M from MVC refers to parts of the business model but it's not the same thing as the business model.
I suggest to take your time and read a bit more about repository pattern and 3-tier architecture and make sure you've understood the concepts and their purpose.

Web API: 'Global' filter not working (ExceptionFilter)

I implemented the exception filter like here: http://www.asp.net/web-api/overview/web-api-routing-and-actions/exception-handling
And registered it globally, like microsoft or stackoverflow-users ( How to add global ASP.Net Web Api Filters? ) explained.
public static void RegisterWebApiFilters(System.Web.Http.Filters.GlobalFilterCollection filters)
{
//other filters
filters.Add(new MyExceptionFilter());
}
But if I throw an exception, my method is not called.
My exception-handling method is called only if I add the attribute [MyExceptionFilter] to the controller-method, but I hoped I can avoid that for all methods by registering the filter globally.
I tried to set a order for the filters, but this had no effect.
Edit: I have noticed, that in the new Wep Api RC the method is called "RegisterGlobalFilters" and this seems to be the MVC filter collection.
If I call
GlobalConfiguration.Configuration.Filters.Add(new MyExceptionFilter());
it works. This is the collection for the Web Api.
Looks like I have to build my own "FilterConfig" class for the web api...
Like I mentioned in my question: There are different filter collections. One for MVC and one for the web api.
If you want to add the filter to the web api, add this line of code to the global.asax
GlobalConfiguration.Configuration.Filters.Add(new MyExceptionFilter());

Edit Models in different MVC project layer

I have a ASP.NET MVC3 solution named "SampleProject". I have 4 projects in the solution.
The project names of the solution are
SampleProject.Data (holds entity classes, DAL classes, and filter classes)
SampleProject.Service (something like BLL in standard ERP)
SampleProject.Tests (test project)
SampleProject.Web (holds controllers and views)
I am calling the Service classes from my controllers. The service classes are calling Data classes and data classes are performing the database operations.
I have done create, list and details part. Now I stucked in Edit part. None of the examples (NerdDinner,MVCMusicStore etc) using my architecture. In the provided examples(NerdDinner,MVCMusicStore etc or in ASP.NET website tutorials), they are just using built in UpdateModel method which I don't want to use. I want to manually get the model object from my view and send it to my Data layer for update.
My question is, how can I update the models through different project layer?
I solved the porblem. Here is the code.Just for reference, CResult is a class which contains IsSuccess(bool), Message(string) properties in it.
CResult oCResult;
[HttpPost]
public ActionResult Edit(Restaurant model)
{
try
{
oCResult = restaurantService.Update(model);
if (oCResult.IsSuccess)
{
return RedirectToAction("Index");
}
return View("Error");
}
catch
{
return View();
}
}
The view engine prepares the object (in my case, it is Restaurant type of object) it inherits with new values and send back to controller. this is my understanding.