I am implementing EHcache in my project and i have written a method that will remove all entries from the cache. The method works fine, here's the code snippet:
public void removeEntriesFromCache(String cacheName){
CacheManager.getInstance.getCache(cacheName).removeAll();
}
I am eventually going to expose this method as a rest service so that user could call the service along with cache name that needs to be invalidated. However, i would want to be able to do the same using #CacheEvict. I know i can do this:
#CacheEvict(name ="myCache" , allEntries=true)
public void removeEntriesFromCache(){
}
But, this method will remove entries from just one cache , in this case it will remove all cache entries from "myCache". I want to be able to resolve the cache name dynamically at runtime as specified by the user.
Is it possible to achieve something like this:
#CacheEvict(name ="${cacheName}" , allEntries=true)
public void removeEntriesFromCache(String cacheName){
}
OR
#CacheEvict(name ="#cacheName" , allEntries=true)
public void removeEntriesFromCache(String cacheName){
}
Your suggestions would be welcome.
Thanks
#CacheEvict documentation clearly states where you can use SpEl. You can't use SpEl in the name attribute, but you can inject CacheManager to the bean you are annotating now, get the Cache by name and clear it.
cacheManager.getCache(cacheName).clear()
Related
I am developing a Spring Boot application. And I have some permission checks in that program that is checked within controller methods. For an example there are some checking methods to check if there is any duplicate records, if that logged in user a member and so on. So what I was thinking is I need to move onto #PreAuthorize. So how can I create custom methods to do those duplicate validations and member validations and used them via #PreAuthorize. I know those duplicate checked can be done in anywhere else but I personally need to use #PreAuthorize. So anybody can help me? I really appreciate that.
You can do this using custom expression with #PreAuthorise
#PreAuthorize("isDuplicate(#id)")
#GetMapping("/organizations/{id}")
#ResponseBody
public Organization findOrgById(#PathVariable long id) {
return organizationRepository.findOne(id);
}
public boolean isDuplicate(Long OrganizationId) {
// add your logic here to check duplicates or any validation
}
refer https://www.baeldung.com/spring-security-create-new-custom-security-expression for more info
I'm developing API using Spring Framework and faced a problem that can be solved by simply adding a necessary logic to every place I have it, but I think that there might be an elegant solution to fix it.
I have the following method in my controller:
#GetMapping("/user/{userId}/permissions")
public List<PermissionDto> list(#PathVariable long userId,
#ModelAttribute #Valid PermissionCriteria criteria) {
return permissionService.list(criteria);
}
The thing is that in dto I have a field called userId. It's made not to have a lot of arguments going to the method of the service. But, I want this user id to be set exactly from path since I use the URL that specifies that we are adding permission exactly to specific user resource. It's doable by making addition line that uses setter in the criteria and sets the value of userId. However, now I should never forget to add this line every time I have a case like that. That's why I decided to move it to InitBinder:
#InitBinder(PERMISSIONS_CRITERIA_NAME)
public void permissionsCriteriaInitBinder(WebDataBinder binder) {
PermissionsCriteria criteria = (PermissionsCriteria) binder.getTarget();
Optional.ofNullable(requestHelper.getUserId())
.map(Long::parseLong)
.ifPresent(criteria::setUserId);
}
It works fine. The user ID is set from the path. However, If I specify request parameter and path variable at the same time, even though userId is set from the path in init binder, it's overridden afterwards before it goes to the controller method. So, this one doesn't solve all the issues.
What I want to find, is someplace where the logic can be put to apply to both init binder(I need it for validation) and controller method. Maybe there is a special type of hook or interceptor or at least something to implement to satisfy this conditions?
I really need your help. I'm using my portlet app as usual when suddenly I have to get out of computer. When I return, there's NullPointerException. OK, why's that? Hmm... my session doesn't contain object it should hold. So, I'm probably loosing something but here's how I always looked at SessionAttributes.
I have my Controller annotated as so:
#SessionAttributes({
SOME_ATTR
})
Then I have a method with following signature:
#Valid #ModelAttribute(SOME_ATTR) SomeObject someObject
And also init method for my session attribute:
#ModelAttribute(SOME_ATTR)
public SomeObject getSomeEmptyObject() {
return someUtils.createSomeObject();
}
When I debugged my app at this point I found out that:
manually looking into the session, there's nothing in it
form is properly binded to someObject
So my two big questions are:
why doesn't Spring set someObject into session as well?
when the session was invalidated, why wasn't getSomeEmptyObject() called to fill the empty space?
Thanks in forward!
Have a look at HttpSessionBindingListener and the HttpSessionAttributeListener. If SomeObject is a class that you control, you can implement HttpSessionBindingListener otherwise you will likely need HttpSessionAttributeListener.
This SO posting covers this pretty well.
Well, do you set your session attribute in proper form:
#SessionAttributes(value = {"user", "register"})
Thats all that I can think about.
in my controller, I need to choose what service implementation I need to use on spring. Before I was encapsulating this code in a factory, but I think that its not a good practice...
#Component
public class StoreServiceFactory {
#Autowired
private List<StoreService> storeServices;
public StoreService getService(){
if(isActiveSale){
return storeServices.get("PublicStoreService")
}
return storeServices.get("PrivateStoreService")
}
}
So I would like to encapsulate this behaviour to not care about inside my controller.. How can I get it??
If isActiveSale changes when the application is running, I think that what you got is a good solution. Since the Controller is a singleton you can't expect a different injection everytime this value changes.
If you get the value only on the startup of the application(e.g. from some property) you can use a profile.
There is nothing wrong with a factory, although as #R4J points out in the comments it is more of a provider, since it doesn't instantiate anything. I would consider the factory/provider a good choice if the 'isActiveSale' status changes based on things outside of the current control flow, like a configuration in a property file. A setting set in some adminstration screen, or maybe based on the time of day.
I have been wrestling with this problem for a while. I would like to use the same Stripes ActionBean for show and update actions. However, I have not been able to figure out how to do this in a clean way that allows reliable binding, validation, and verification of object ownership by the current user.
For example, lets say our action bean takes a postingId. The posting belongs to a user, which is logged in. We might have something like this:
#UrlBinding("/posting/{postingId}")
#RolesAllowed({ "USER" })
public class PostingActionBean extends BaseActionBean
Now, for the show action, we could define:
private int postingId; // assume the parameter in #UrlBinding above was renamed
private Posting posting;
And now use #After(stages = LifecycleStage.BindingAndValidation) to fetch the Posting. Our #After function can verify that the currently logged in user owns the posting. We must use #After, not #Before, because the postingId won't have been bound to the parameter before hand.
However, for an update function, you want to bind the Posting object to the Posting variable using #Before, not #After, so that the returned form entries get applied on top of the existing Posting object, instead of onto an empty stub.
A custom TypeConverter<T> would work well here, but because the session isn't available from the TypeConverter interface, its difficult to validate ownership of the object during binding.
The only solution I can see is to use two separate action beans, one for show, and one for update. If you do this however, the <stripes:form> tag and its downstream tags won't correctly populate the values of the form, because the beanclass or action tags must map back to the same ActionBean.
As far as I can see, the Stripes model only holds together when manipulating simple (none POJO) parameters. In any other case, you seem to run into a catch-22 of binding your object from your data store and overwriting it with updates sent from the client.
I've got to be missing something. What is the best practice from experienced Stripes users?
In my opinion, authorisation is orthogonal to object hydration. By this, I mean that you should separate the concerns of object hydration (in this case, using a postingId and turning it into a Posting) away from determining whether a user has authorisation to perform operations on that object (like show, update, delete, etc.,).
For object hydration, I use a TypeConverter<T>, and I hydrate the object without regard to the session user. Then inside my ActionBean I have a guard around the setter, thus...
public void setPosting(Posting posting) {
if (accessible(posting)) this.posting = posting;
}
where accessible(posting) looks something like this...
private boolean accessible(Posting posting) {
return authorisationChecker.isAuthorised(whoAmI(), posting);
}
Then your show() event method would look like this...
public Resolution show() {
if (posting == null) return NOT_FOUND;
return new ForwardResolution("/WEB-INF/jsp/posting.jsp");
}
Separately, when I use Stripes I often have multiple events (like "show", or "update") within the same Stripes ActionBean. For me it makes sense to group operations (verbs) around a related noun.
Using clean URLs, your ActionBean annotations would look like this...
#UrlBinding("/posting/{$event}/{posting}")
#RolesAllowed({ "USER" })
public class PostingActionBean extends BaseActionBean
...where {$event} is the name of your event method (i.e. "show" or "update"). Note that I am using {posting}, and not {postingId}.
For completeness, here is what your update() event method might look like...
public Resolution update() {
if (posting == null) throw new UnauthorisedAccessException();
postingService.saveOrUpdate(posting);
message("posting.save.confirmation");
return new RedirectResolution(PostingsAction.class);
}