Dependency Injection vs Request Scope - java

I have an Spring Rest application, in which there's a requirement to get some access token in a service(Annotated with #Service) class. The token generation is in a separate class(Annotated with #Component) and the requirement given is to get a unique token for each new request. And I'll be using the generated token two times within the same request in the service class. Now the questions are as follows.
I can inject the tokenGenerator class using #Autowired. And get the token, store it in the private instance variable inside the class and use it wherever I wanted inside the service class. Is it the correct approach to store a value that should live as long as the request is alive. When I tested this approach I find the same access token is printed across the methods in service class for a single request. what would go wrong here?
Another approach I tried was using WebApplicationContext.SCOPE_REQUEST on the TokenGenerator class and use the Provider in my service class to get the class instance and then access token from it. This also works the same way as the previous approach. If so why do I even need to use the approach for request scoped values?
Approach 1:
Here I have used the dependency injection to get the access token.
#Component
public class TokenGenerator
{
public string getToken();//okhttp Rest API Call
}
#Service
public class ServiceClass{
#Autowired
TokenGenetor token;
private String tokenValue;//**setTokenValue as setter**
public void method1()
{
setTokenValue(token.getToken());
}
public method2(){print(tokenValue)}// prints 1234abcd
public method3(){print(tokenValue)}// prints 1234abcd
}
Approach 2:
Here I have used the RequestScope to get the access token. and Used the Provider to get the instance in the service class.
#Component
#scope(WebApplicationContext=scope_request)
public class TokenGenerator
{
public string getToken();//okhttp Rest API Call
}
#Service
public class ServiceClass{
#Autowired
private Provider<TokenGenetor> token;
private String tokenValue;//setTokenValue as setter
public void method1()
{
// Not Setting anything
}
public method2(){print(token.get().getToken();)}// prints 1234abcd
public method3(){print(token.get().getToken();)}// prints 1234abcd
}

Related

How to parse JWT token in unit tests SpringBoot

I have a microservice setup with Spring boot and OAuth 2 with JWT.
I have additional fields in my JWT token.
Most of my services call a static method that has a thread local of the additional fields in the token.
How can I write unit tests for such services?
Even if I tried to inject a mock user it doesn't work and I couldn't find a way of sending the JWT because I am no testing the controllers.
Code:
SecurityUtils static Calss (also check the package for other relevant JWT handler) .
Example on a method that will call the static class (Line 79).
Method:
public CommonResponse saveUpdateProfile(ProfileRequest request) {
String authUsername = SecurityUtils.getUsername();
Optional<ProfileEntity> optionalProfile = findProfileByUsername(authUsername);
ProfileEntity profile;
if (optionalProfile.isPresent()) {
profile = optionalProfile.get();
} else {
profile = ProfileEntity.builder()
.username(authUsername)
.build();
}
profile.setFirstName(request.getFirstName());
profile.setLastName(request.getLastName());
ProfileEntity savedProfile = profileRepository.save(profile);
if (savedProfile == null) {
throw new RuntimeException("Failed to save user in database");
}
return CommonResponse.ok(savedProfile);
}
I appreciate all the help.
Ok, so that's a common problem when using static methods. You can't easily override them, e.g. in tests. I think what I would do is to turn your SecurityUtils class into a service and make it implement an interface. Then inject this interface into any other service that needs to use it, instead of calling static methods. Then you can easily provide another implementation to your tests.
So you would have something like that:
interface SecurityUtils {
String getUsername();
...
}
#Service
class MySecurityUtils immplements SecurityUtils {
private JwtToken getJwtToken() {
return MySecurityContextHolder.getContext().getJwtToken();
}
public String getUsername() {
return getJwtToken().getUsername();
}
...
}
Then in the unit test you can just inject a mock implementation of SecurityUtils to any class you're testing.

Java Rest Best Practices

I'm new to rest webservice and have a novice q'. I've created a rest class and would like to use helper classes to handle certain operations. So for example I've created the following service:
import statements...
#Path("/UserResources")
public class UserResource {
//Create Spring application context
static ClassPathXmlApplicationContext ctx = new
ClassPathXmlApplicationContext("classpath:/spring.xml");
private UserResourceHelper urh = new UserResourceHelper(); // this is the helper
class UserProfileService userProfileService = ctx.getBean(UserProfileService.class);
#POST
#Path("/createUser")
#Consumes(MediaType.APPLICATION_JSON)
public Response createUser(#Context HttpServletRequest request, Object object) {
StringBuffer sb = new StringBuffer();
User user = userProfileService.findByPrimaryKey(object);
sb.append(urh.createUser(object));
return
Response.status(Status.CREATED.getStatusCode()).entity(result.toString()).build(); } }
I have a couple of questions on this approach:
Is this the correct way to instantiate the helper class? Or should I create a constructor and instantiate the class there? for example:
public UserResource (){
urh = new UserResourceHelper();
}
On this approach will there always be a new instance of the UserResourceHelper?
If so that would mean there will not be an issue on concurrency correct? ie. 2 requests coming in at the same time and the 1st object being received by the createUser method would suddenly get replaced by the 2nd object that suddenly came in?
I'm using Hibernate for ORM. Is the way i've instantiated the entities as per my code sample correct?
Thanks for your assistance!
On this approach will there always be a new instance of the UserResourceHelper?
yes. It always creates new instance
Suggestion:
If you want to create a new service for every request, you can make this as a service instead of a helper class and you can autowire the service in the controller.
#Service
public class UserResourceService {
}
and in the controller
public class someController {
#Autowired
private UserResourceService userResourceService;
}
You can use #Autowire annotation in spring boot, it will automatically create instance of class
#Autowire
UserResourceHelper userResourceHelper;

Is the repo class thread safety for concurrent requests? - Spring boot

I'm using Spring boot with jetty embedded web server for one Web application.
I want to be 100% sure that the repo class is thread safety.
The repo class
#Repository
#Scope("prototype")
public class RegistrationGroupRepositoryImpl implements RegistrationGroupRepository {
private RegistrationGroup rg = null;
Integer sLastregistrationTypeID = 0;
private UserAccountRegistration uar = null;
private List<RegistrationGroup> registrationGroup = new ArrayList<>();
private NamedParameterJdbcTemplate jdbcTemplate;
#Autowired
public RegistrationGroupRepositoryImpl(DataSource dataSource) {
this.jdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
}
public List<RegistrationGroup> getRegistrationGroups(Integer regId) {
// Some logic here which is stored in stored in the instance variables and registrationGroup is returned from the method
return this.registrationGroup;
}
And the Service class which invoke the getRegistrationGroups method from the repo.
#Service
public class RegistrationService {
#Autowired
private Provider<RegistrationGroupRepository> registrationGroupRepository;
public List<RegistrationGroup> getRegistrationGroup() {
return registrationGroupRepository.getRegistrationGroups(1);
}
}
Can I have race condition situation if two or more request execute the getRegistrationGroups(1) method?
I guess I'm on the safety side because I'm using Method injection (Provider) with prototype bean, and every time I'm getting new instance from the invocation?
First of all, making your Bean a prototype Bean doesn't ensure an instance is created for every method invocation (or every usage, whatever).
In your case you're okay on that point, thanks to the Provider usage.
I noticed however that you're accessing the getRegistrationGroups directly.
return registrationGroupRepository.getRegistrationGroups(1);
How can this code compile? You should call get() on the Provider instance.
return registrationGroupRepository.get().getRegistrationGroups(1);
Answering your question, you should be good to go with this code. I don't like the fact that you're maintaining some sort of state inside RegistrationGroupRepositoryImpl, but that's your choice.
I always prefer having all my fields as final. If one of them requires me to remove the final modifier, there is something wrong with the design.

Intercept the instance of an object from RestController or Hibernate in Spring before it's returned to the client

I'm developing a translation service that currently works inside another Service. For example:
public Profile getById(int chainId, int profileId, Integer languageId) {
Profile profile = profileRepository.getById(chainId, profileId);
translationService.translate(profile, languageId); // Here
return profile;
}
Now, to avoid to use a translate method on every service method of all the application, and as I only have the language of a user from the controller, I would like to execute the translate method before every Profile (and any other object) is returned to the client.
I tried to implement HandlerInterceptor in a custom interceptor, but it seems it doesn't returns the instance of the object that I'm returning. Anyone could help?
Another way to do it could be to translate every object that came from a select in Hibernate, but I also don't find any good solution to it this way...
The solution was to use Spring AOP. Probably the question wasn't very well explained, but what we needed was a way to intercept the object a user was asking to the backend, because they are able to create their own translations and we save them in the database. We had to return the model with the correct translation for each user, who has their localization in their profile. Here's the way we intercept it:
#Component
#Aspect
public class TranslatorInterceptor extends AccessApiController {
Logger logger = LoggerFactory.getLogger(this.getClass());
#Autowired
public TranslationService translationService;
#Pointcut("execution(* com.company.project.api.controller.*.get*(..))")
public void petitionsStartWithGet() { }
#Pointcut("execution(* com.company.project.api.controller.*.list*(..))")
public void petitionsStartWithList() { }
#Pointcut("execution(* com.company.project.api.controller.*.find*(..))")
public void petitionsStartWithFind() { }
#AfterReturning(pointcut = "petitionsStartWithGet() || petitionsStartWithList() || petitionsStartWithFind()", returning = "result")
public void getNameAdvice(JoinPoint joinPoint, Object result){
translationService.translate(result, getCustomUserDetails().getLanguageId());
logger.debug("Translating " + result.getClass().toString());
}
}
What we do here is to "watch" all the methods in the package "controller" that start by 'get', 'list' or 'find' (getById(), for example) and through this advice, we intercept the object before is sent to Jackson. The method getCustomUserDetails comes from AccessApiController, which is a class we did to provide our Controllers with some information we need.

How to access configuration in a Lagom service at startup?

I am migrating my current app in Spring/J2EE to Lagom. I am working in Java. I need to read variables from the configuration (application.conf in resources folder). In the implementation module, I try to inject configuration as a class variable like this
#Inject
private Configuration config
but when I access this config object in the constructor, it gives null pointer exception.
The whole code is like this
import play.Configuration;
public class SomeServiceImpl implements SomeService {
#Inject
private Configuration config;
public SomeServiceImpl() {
//getting configuration from application.conf
// gives exception as config is null.
String key = config.getString(“key”);
}
#Override
public ServiceCall<Request, Response> send() {
//works here, does not give exception
String key = config.getString(“key”);
}
}
Sorry, I should have been clear from the beginning. I have edited the original question. I get null pointer exception when I try to read from configuration object in constructor but I am able to use it in service call implementation. I want some way in which I can access the configuration in application.conf at startup and possibly store in some config class which can be accessed anywhere later.
In Java, when an object is instantiated, the first thing that happens (before anything else can possibly happen) is the constructor is invoked. After that, frameworks like Guice (which Lagom uses) are free to inject things, but they can't do it until the constructor has been invoked. So, all your #Inject annotated fields will be null when the constructor is invoked, there is nothing you can do to work around that.
So, don't use field injection, use constructor injection, eg:
import play.Configuration;
public class SomeServiceImpl implements SomeService {
private final Configuration config;
#Inject
public SomeServiceImpl(Configuration config) {
this.config = config;
String key = config.getString("key");
}
#Override
public ServiceCall<Request, Response> send() {
String key = config.getString("key");
}
}
Constructor injection is not just recommended for this use case, you should be using it everywhere, it avoids all these potential issues.

Categories