I have a scenario where we support 2 different types of authenticated users (UserTypeA, UserTypeB), but they will never be used in the same server environment. Right now, we use 2 different url paths /path/usertypea/list vs /path/usertypeb/list. We would like to make them use the same path if possible, for example /path/list, and have an environment variable be the condition to know where to route the traffic. The parameters for each user type aren't exactly the same, there are some differences in how the data is organized. We're using Jersey.
I've tried a few things like Singleton classes: https://eclipse-ee4j.github.io/jersey.github.io/documentation/latest/user-guide.html#d0e2650 / https://stackoverflow.com/a/33585724/12183373 but it never routes the value, it just returns the name of the class instead of the JSON payload I'm expecting.
Here's some of the code:
#Path("/list")
public class GlobalSegmentServiceRouter {
#GET
#Produces("application/json")
public Class<?> findAll() {
boolean isUserTypeA = false;
if (isUserTypeA) {
return UserTypeAService.class;
} else {
return UserTypeBService.class;
}
}
}
Then I have 2 separate class files for the following:
#Singleton
public class UserTypeAService {
public List<String> findAll(/*Parameters for A*/) {
// Do work here for User Type A
}
}
#Singleton
public class UserTypeBService {
public List<String> findAll(/*Parameters for B*/) {
// Do work here for User Type B
}
}
When I try and hit the endpoint, this is the response I get:
"com.test.services.UserTypeAService"
Any suggestions on how to accomplish this?
add some flag for checking which kind of user is logged in to a custom principal impl. Then you can inject the current user and then call UserTypeAService.findAll or UserTypeBService.findAll in your method.
#GET
#Path("/path/list")
public String yourMethod(#Context SecurityContext securityContext)
Related
If I have a Get request that returns orders of clients, how can I filter the response to give me the objects that have a specific value for example that are made by those specific clients in Spring Boot?
I have tried with #PathVariable and #RequestParams but every attempt failed.
Thank you in advance.
If you want to show a specific order which has an identifier of some sort, use #PathVariable. In the following example, the identifier is a String, but in many case it will rather be long or an Integer.
#RestController
#RequestMapping("/orders")
public class OrdersController {
#GetMapping("/{id}")
public Order getOrder(#PathVariable("id") String id) {
// get the order with a specified id from the backend
}
}
The web request in this case will look like http:/<host>:<port>/orders/123
If you want to filter the order by some name, like 'madeBy John', use Request parameter:
#RestController
#RequestMapping("/orders")
public class OrdersController {
#GetMapping("/")
public List<Order> getOrdersFilteredByName(#RequestParam("madeBy") madeBy) {
// get the order filtered by the person who made the order
// note, this one returns the list
}
}
In this case the web request will look like this: http:/<host>:<port>/orders?madeBy=John
Note that technically you can implement whatever you want at the backend, so you can pass, say, John in the first example as a path variable, on server its a String after all, however what I've described is a straightforward and kind-of-standard way of doing these things - so can expect to see this convention in many projects at least.
#RestController
#RequestMapping("/order")
public class OrderController {
// http://<host>:<port>/order/1
#GetMapping("/{id}")
public Order getOrder(#PathVariable Long id) {
// Return your order
}
// http://<host>:<port>/order?madeBy=John
#GetMapping("/)
public List<Order> getOrdersMadeBy(#RequestParam("madeBy") String madeBy) {
// Return your order list
}
}
In simple words... imagine I have a class like this:
#Path("/someUniquePath")
public class AuthorizePerson
{
#GET
public Response authorizeMeGetRequest(... any # of parameters)
{
return authorize(... any # of parameters);
}
public Response authorize()
{
// check if I'm a human
// check if I have roles A, B, then C
return Response.ok().build();
}
}
Now say I have another resource:
#Path("/someUniquePath")
public class AuthorizeSpecificPerson extends AuthorizePerson
{
#GET
public Response authorizeMeGetRequest(... any # of parameters)
{
// Do something
// if I'm 6 ft tall
return authorizeTallPerson();
// else
return authorize();
}
public Response authorizeTallPerson()
{
// check if I'm a human
// check if I have roles A
// use role A to determine if I'm a tall person
// check for roles B, C
return Response.ok().build();
}
Now to handle re-using code, I was thinking to have another class that can provide me with the methods that I can call as needed, I'm taking the composition approach.
but then my method becomes
public Response authorizeTallPerson()
{
myClass.checkIfHuman();
myClass.checkIfRoleA();
myClass.checkIfTallPerson();
myClass.checkIfRoleBAndC();
return Response.ok().build();
}
And my base class becomes:
public Response authorize()
{
myClass.checkIfHuman();
myClass.checkIfRoleA();
myClass.checkIfRoleBAndC();
return Response.ok().build();
}
Notice there is still patterns. Both need to check if the person is a human and if they have role A. It seems like I'm just re-using code re-use... like its becoming nested. I hope this makes sense... how can I handle this?
It's not as simple as having a common method that performs both tasks:
public Response checkCommon()
{
myClass.checkIfHuman();
myClass.checkRoleA();
return Response.ok().build();
}
because then my callers need to make conditional decisions... if the user is not human, authorize method needs to return a different type of Response etc.
We are using Guice in our project for DI. Currently we have some configurations(properties) that we load a t server startup from a file. These are then bound to all the components & used for all the requests.
But now, we have multiple property files & load them at startup. These configurations can be different per REST(Jersey) request as they depend on the input.
So, we need to bind these configurations dynamically for each request. I looked into Guice API for #RequestScoped, but did not find anything specificallyu helpful.
There are few questions similar to this, but no luck yet. Can you please help me with this.
I'm providing 2 ways of doing this and both are request scoped.
Using HttpServletRequest, for classes where you can Inject request object.
Using ThreadLocal, Generic way. It can be used in any class.
(NOTE: This method wouldn't work if your creating new threads in your code and want to access the value. In which case you'll have to pass the values through Objects to those threads)
I meant something like this:
public class RequestFilter implements ContainerRequestFilter {
#Context
private HttpServletRequest request;
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
List listOfConfig = //load Config;
request.setAttribute("LOADED_CONFIG",listOfConfig);
// If you want to access this value at some place where Request object cannot be injected (like in service layers, etc.) Then use below ThreadLocals.
ThreadLocalWrapper.getInstance().get().add("adbc"); // In general add your config here, instead of abdc.
}
}
My ThreadLocalWrapper looks like this:
public class ThreadLocalWrapper {
private static ThreadLocal<List<String>> listOfStringLocals; // You can modify this to a list of Object or an Object by itself.
public static synchronized ThreadLocal<List<String>> getInstance() {
if (listOfStringLocals == null) {
listOfStringLocals = new ThreadLocal<List<String>>() {
#Override
protected List<String> initialValue() {
return new ArrayList<String>();
}
};
}
return listOfStringLocals;
}
}
To Access the value:
In Controller - Inject HttpServletRequest Object and do getAttribute() to get the value. Since HttpServletRequest Object is requestScoped, you can set the loaded config. into this and access it in your controller's using request Object again.
In Any other part of the code - If HttpServletRequest is not available then you can always use the ThreadLocal example shown. To access this value.
public class GuiceTransactionImpl implements GuiceTransaction {
private String value = "";
public GuiceTransactionImpl(String text) {
value = text;
}
#Override
public String returnSuccess() {
return value + " Thread Local Value " + ThreadLocalWrapper.getInstance().get();
}
}
As i understand spring mvc controllers are thread safe by default (like servlets). But I just want to know any private helper methods inside the controllers are thread safe ?
I have two mapping in the controller class eg: /test and test/success. Every time user invokes this url I want to check the user status and activation time in the database using a service method ( two different calls ). So I have decided to create a one private helper method to check the status.
So could anyone know that my private method is thread safe ?
All request are handled by one instance of your controller (singleton because it's a spring managed bean). So you need to make sure to not store any state (in a field) related to one request.
So:
#Controller
#RequestMapping("/foo")
public class Foo {
#Autowired
private Something something;
#RequestMapping("/list")
public String foo() {
something.someMethod();
bar();
return "view"
}
private void bar() {
// something
}
}
is OK, but:
#Controller
#RequestMapping("/foo")
public class Foo {
private User theUser; // problem is ALL request share this field
#RequestMapping("/foo/{userId}")
public String foo(#PathVariable final Integer userId) {
if (theUser.getId().equals(userId)) {
// something
} else {
theUser = ...
}
return "view"
}
}
is not.
NB: not tested (typed just here so it can even hurts your compiler)
Apologies if this has been answered already - I've had a look and can't find anything.
Using the Play framework, I have defined two controllers - one is a public API that returns JSON, and one is a consumer of this API which presents the JSON as HTML. E.g. my routes file look as follows:
GET /foos controllers.App.foos() #produces HTML
GET /api/foos controllers.API.foos() #produces JSON
A requirement of the project is that our data should only be accessed via our public API. Therefore, the way that I'd like to implement this is to have App.foos() invoke API.foos(), parse the JSON result, and pass it to a template to be rendered. For example:
public App extends Controller {
public static Result foos() {
Result result = API.foos();
// TODO: get the JSON out of the result object
}
}
Can anyone tell me how I can extract the JSON from the result object? I can get the body of the object as an Enumerator using ((SimpleResult)result.getWrappedResult()).body(), but I am still unclear how I can get out the JSON.
Because I am new to the Play framework, perhaps I am going about this wrong and there is an easier/better way to do this?
Many thanks in advance,
James
The easiest way would be to expose the underlying method.
public Api extends Controller {
public static Result foos() {
Ok(foosJson());
}
public static JsValue foosJson() {
// ...
}
}
public App extends Controller {
public static Result foos() {
JsValue json = API.foosJson();
}
}