Including tenant id in url using spring-boot and HATEOAS - spring

I'm currently migrating a legacy multi tenant REST backend to spring-boot. All the environment is set to include the tenant ID in URL.
I've managed to do this implementing my own Rest Controller defining the class using, for example, somthing like this:
#RestController()
#RequestMapping("/*/invoices")
public class InvoiceController {
#Autowired
private InvoiceRepository invoiceRepository;
#GetMapping("/{id}")
public ResponseEntity<Invoice> findById(#PathVariable("id") Long id) {
return ResponseEntity.of(invoiceRepository.findById(id));
}
}
and capturing the tenant id using a HandlerInterceptor. This works very well.
Now, I would like to use the HATEOAS implementation and don't implement the #RestController, but I can't set any way to capture the Tenant Id and extract that part from the URL. I don't find any way to configure this for the RepositoryEntityController class.
Could anyone give me some guidance to achive this.
Thanks.
I would like to use an URL with a path like "/ten1/invoices" and use a HATEOAS RestController exported by the InvoiceRepository class.

Related

Spring kotlin - How to inject internal class to public class

I have some problem but also I don't know if my approach is right so I decided to ask you about it. I try to create public facade (for REST controllers or another modules) in application layer which should communicate with domain layer. The problem is that it seems to me that everything in domain should be internal and when I want to inject some service from domain to facade then intellij returns me error: 'public' function exposes its 'internal' parameter type SomeService. What is the best approach for this case? Should I make interface SomeService as public? But then any other modules also could inject it what is probably wrong :/
example code:
applicaion layer:
class MyFacade(
private val myInternalService: InternalService
){
fun save(...){
return myInternalService.save(...)
}
}
domain layer:
internal interface InternalService {
fun save(...)
}
and rest implementation of domain...

How to expose the resourceId with Spring Data Rest

I had was to expose the primary key which is annotated with #Id in entity.the ID field is only visible on the resource path, but not on the JSON body.
You can configure this using the RepositoryRestConfigurerAdapter on entity level.
#Configuration
public class ExposeEntityIdRestConfiguration extends RepositoryRestConfigurerAdapter {
#Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.exposeIdsFor(MyEntity.class);
}
}
Be aware that using this you are working against the principles of spring-data-rest - sdr promotes hypermedia to be able to use an API by navigating between resources using links - here your resources are identified and referenced by links and thus the ids are not needed anymore. Using ids on your client pushes the complexity of constructing links to resources to the client. And the client should not be bothered with this knowledge.
The best solution would be not to using the IDs of your entities, and use the link references the hypermedia provides.
You just need to parse your JSON accordingly to the HAL specification used by Spring Data Rest.

How to obtain getUserPrincipal().getUserName() while implementing Spring Data JPA AuditorAware interface

I'm trying to use Spring Data JPA (1.6.2) in my current project. All seems to work well, but I got stuck while implementing the AuditorAware interface.
My application will be deployed to an old Apache Jetspeed JSR168 compliant portal. This portal takes care of user authentication/authorisation. As such, I don't have to use a security framework like Spring Security or Shiro. The other frameworks in my application are:
Struts 1.2.4 (with a Struts-Portal-Bridge)
Spring 3.2.10
JPA (Hibernate 3.6.10 as ORM provider)
I'd like to use #CreatedBy and #LastModifiedBy annotated fields in my entities (I got #CreatedDate and #LastModifiedDate working). In my application I usually obtain the username using request.getUserPrincipal().getUserName().
But how can I get hold of the username while implementing the AuditorAware interface?
The example implementation from the Spring Data JPA docs:
class SpringSecurityAuditorAware implements AuditorAware<User> {
public User getCurrentAuditor() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !authentication.isAuthenticated()) {
return null;
}
return ((MyUserDetails) authentication.getPrincipal()).getUser();
}
}
Somehow I want to implement AuditorAware like this:
class MyAuditorAware implements AuditorAware<String> {
public String getCurrentAuditor() {
return <<principal from servlet- or portletcontext>>.getUserName();
}
}
How can I accomplish this without adding an additional framework?
As Konstantin already mentioned in his comment, you probably want to save the principal name in a scope suitable for a request. This may very well be a ThreadLocal. This allows you to get it easily later on in your AuditorAware implementation.
To stay with Spring's naming call it PrincipalContextHolder. As a starting point you may look at the source of JodaTimeContextHolder for a simple implementation of a ContextHolder.

Spring RequestMapping parameter custom annotation

in my web application I have many places where I need to retrieve current logged account (from session).
Account account = getAccountFromSession(session);
This piece of code is repeated many many times. I wonder if this is possible to make my request look something like this:
#RequestMapping(value="/something", method=RequestMethod.POST)
public String handleSomething(
#RequestParam String someParam,
#Account Account account) { ... }
where #Account is my custom annotation.
How can I tell spring to process this annotation?
Use HandlerMethodArgumentResolver (or WebArgumentResolver for versions below 3.1).
To enable your argument resolver:
If you use #EnableWebMvc - make your #Configuration implement WebMvcConfigurer and override addArgumentResolvers()
If you use <mvc:annotation-driven> - use argument-resolvers attribute
For older versions you may need to declare AnnotationMethodHandlerAdapter manually and set its customArgumentResolvers

JIRA Rest Service with Bandana Manager

I have a JIRA plugin that I'm developing that has a REST service. That service should be able to accept POSTed requests, unmarshall some data and store it. The seemingly suggested way to do this in JIRA is to make use of the Bandana persistence framework. According to this page, I should be able to simply define a setter that Spring should call to give me my Bandana manager.
#Path("/path")
public class SCMService {
private BandanaManager bandanaManager;
// setter called by Spring
public void setBandanaManager(BandanaManager bandanaManager) {
this.bandanaManager = bandanaManager;
}
//...More methods...
}
However, when I test this, the setter is never being called and my manager is null. I'm guessing this should be as simple as registering this service with Spring for injection somehow but I can't seem to find anything like that.
How would I get my setter called? Is there a better way to do this?
Er, I'm not sure that JIRA uses Bandana in that way, though Confluence does. You can certainly post data to a JIRA rest resource and then store it using properties tables
Something like this:
#POST
#Consumes (MediaType.APPLICATION_XML)
public Response createComponentAndIssues(#Context HttpServletRequest request, ...

Resources