I'm migrating to SpringMVC and Apache Tiles 3 from a Strut1 + Tiles project. I know only a little about Struts1+Tiles, it is too old and I'm stuck in Controller and ComponentContext in Struts-tiles. According to document from apache website, it was replaced by ViewPreparer and AttributeContext but I dont know the following line means:
ComponentContext compContext=(ComponentContext)pageContext.getAttribute(ComponentConstants.COMPONENT_CONTEXT,PageContext.REQUEST_SCOPE);
What is ComponentConstants.COMPONENT_CONTEXT? and how to change ComponentContext to AttributeContext
Please Help, Thanks.
Bidi, there are 2 ways of getting an AttributeContext:
The first one, like mck stated: through "org.apache.tiles.AttributeContext.STACK" key of request scope. However, the value is a STACK that contains 2 elements of AttributeContext type. The one we need is the first element. IMHO, this way is limited because since the data structure is a stack, getting also mean removing from the stack according to FIFO rule, so you can use the object for only once.
I am using the second way in my project. Because the execute() method of ViewPreparer already have a parameter of AttributeContext type, and this method is always called each time a page is rendered, so you can use this object to do the thing you want (or put it in request) when overriding the method.
AttributeContext is just a collection of key/value pairs. Normally, people use it to get access to some values which are attributes in the template, so fetching the values and putting them to the request can save the overhead. You can also create some static properties of the inheriting class and setting the values to them.
With the Spring-4 and Tiles-3 integration set up (there's spring docs on this as well as a number of good tutorials around) then the properties you put into spring's model map will be available in your jsps, this is not related to the AttributeContext.
AttributeContext only the other hand is (basically) only for holding the map of attributes. Attributes here are defined within a definition, used to identify template or string attributes (as is typically declared in you xml definitions), and come with properties of role, renderer, expression, and/or value.
If AttributeContext is what you are after: you can get hold of it through the current tilesContainer, and to get hold of the current container use the static TilesAccess, eg
TilesContainer tileContainer = TilesAccess.getCurrentContainer(request);
AttributeContext attributeContext = tilesContainer.getAttributeContext(request);
Bidi,
take a read of http://tiles.apache.org/framework/tutorial/advanced/runtime.html
particular the "Runtime Composition using APIs" section.
TilesContainer container = TilesAccess
.getContainer(request.getSession().getServletContext());
Request tilesRequest = new ServletRequest(
container.getApplicationContext(),
request,
response);
otherwise i suggest you take a dive into the Tiles codebase, it's not complicated code, especially the TilesAccess, Request, ApplicationContext stuff.
Related
There is a class annotated with RestResource (Spring 3.1, Jackson 2.3).
When we try save object A like that
A: {"prop1":1, "prop2":2}
it saved successfully.
We have following code:
A.setProp2(null);
EntityService.patch(A);
A: {"prop1":1, "prop2":null}
After EntityService.patch(A) execution there is no changes in DB (Oracle 11g), but we want that in DB prop2 will be equals to null too.
Is it a normal behaviour (I think maybe yes, because null-value may understanding like not changed)?
Is there a simple way to change this behaviour?
When speaking about the HTTP verbs, the PATCH request describes the differences that should be made to the existing object. It is made so that you can easily create partial updates without exposing a particular resource property throught REST.
In Spring framework, in the context of PATCH request, the null value of a property means no change to the property should be made. I guess that spring data rest transpons this logic to the service layer, so in order to actually update your resource with the null value you should issue a call corresponding to the PUT semantics
So, the answer above is right.
Unfortunately, PUT method update all fields and in some cases it maybe a bad solution. For example if we have many nulls in JSON-object, which wasn't modified.
To make Spring PATCH update null values, only when it's change, the best way that I found is extend DomainObjectMerger class.
It is a bean of REST MVC config, in which we can override method merge (entity.doWithProperties(new SimplePropertyHandler() {}).
In this method we can add addition condition like
sourceValue != targetValue;
independent on null value of sourceValue variable.
I have a API endpoint method like this:
#ApiMethod(name = "test")
public TestModel test(#Named("testArray") ArrayList<String> myTest) {
for (String i:myTest){
log.warning("i=="+i);
}
A request is made as such:
{
"testArray":[
"ID1",
"ID2"
]
}
However, when I check my log (and also the problems this caused in my app), I see
i=="ID1,ID2"
not how i expected to see:
i=="ID1"
i=="ID2"
as the output. It is putting both elements of the array into myTest(0).
How do I populate the Array correctly?
This issue doesn't appear to occur on the latest SDK 1.9.22.
I'm wondering how you're creating the request, and if it's possible that you're just joining the strings with commas as a single element in the array that you send. While I know it sounds crazy to do this deliberately and I don't think you're doing that, it's possible that some layer of abstraction below your code does it?
Another possibility is that you're not using the generated client library for your Endpoints API (you really should, it does a lot of work that you'd end up replicating on your own), and you're forming raw JSON to send over? In that case, I can see how maybe the request that ultimately gets sent might be different from what you expect, collapsing all the values inside the array that "testArray" is a key to into a comma-separated list.
So, my best advice is to examine how you form the request, and if possible, get access to the raw request itself inside your endpoints method to see what was sent.
The easiest way, since this seems like a bug, is to not use a named parameter. Create a new request class that has a list field and use that as an unnamed (aka resource) parameter, instead.
I am using Spring 3.2 and I am looking for a way that I can force controllers to specify which attributes allowed to be bound, so malicious users can not inject values into bound objects.
Spring recommends using setAllowedFields() to white-list / setDisallowedFields() to black-list.
Instead of doing manually this white-list, I want to do this dinamically, so I want to bound that attributes that are visible on the form.
So is it possible to get this white-list? Is there any way that I can get the visible attributes on the form?
Thanks.
You could implement a RequestDataValueProcessor especially the method processFormFieldValue. You could construct a collection of allowed field names, store this in the session.
Next you would extend the ConfigurableWebBindingInitializer and override the initBinder method. Which would retrieve the collection and pre-configure the WebDataBinder there.
And finally you would need some configuration to wire everything together.
Links
RequestDataValueProcessor javadoc
ConfigurableWebBindingInitializer javadoc
In a web application that uses Spring Data JPA with Hibernate, we utilize the web pagination functionality to provide paging and sorting capabilities in various lists of entities.
#Controller
public class MyEntityController {
#RequestMapping(method = RequestMethod.GET)
public ModelAndView list(Pageable pageable) { ... }
}
#Configuration
public class MyWebMvcConfig extends WebMvcConfigurationSupport {
#Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
super.addArgumentResolvers(argumentResolvers);
argumentResolvers.add(new PageableArgumentResolver());
}
}
public interface MyEntityRepository extends PagingAndSortingRepository<MyEntity, String> {
Page<MyEntity> findByPropertyX(String propertyX, Pageable pagable);
}
This allows for entity properties to be defined in the rendered html as special sort request parameters, where the page.sort value actually matches a property in the entity upon which to sort.
<table>
<thead>
<tr>
<th>Property X</th>
<th>Property Y</th>
</tr>
</thead>
<tbody>...</tbody>
</table>
This produces a resulting URL such as:
http://host/context-root/entities/?page.sort=propertyX&page.sort.dir=asc
The problem is that users may modify the URL to use invalid page.sort properties that either reference non-existent column/property names, or worse, that use invalid JPA query characters that result in invalid syntax.
For example, if the URL is modified to sort on "noSuchProperty":
http://host/context-root/entities/?page.sort=noSuchProperty&page.sort.dir=asc
But this property doesn't exist, the following exception will be thrown:
java.lang.IllegalArgumentException: No property noSuchProperty found for type class com.my.company.MyEntity
at org.springframework.data.repository.query.parser.Property.<init>(Property.java:76)
. . .
at org.springframework.data.repository.query.parser.AbstractQueryCreator.createQuery(AbstractQueryCreator.java:86)
. . .
at $Proxy68.findByPropertyX(Unknown Source)
at com.my.company.MyEntityRepository.findByPropertyX(MyEntityRepository.java:17
Likewise, if the URL is modified to an invalid query syntax character, such as """:
http://host/context-root/entities/?page.sort=%22&page.sort.dir=asc
The following error will occur:
java.lang.StackOverflowError
java.util.regex.Pattern$GroupTail.match(Pattern.java:4227)
. . .
org.springframework.data.repository.query.parser.Property.create(Property.java:326)
org.springframework.data.repository.query.parser.Property.create(Property.java:326)
org.springframework.data.repository.query.parser.Property.create(Property.java:326)
org.springframework.data.repository.query.parser.Property.create(Property.java:326)
(There is also a third flavor of exceptions which results in a org.hibernate.QueryException when the #Query is explicitly defined on the Repository method.)
Spring Data JPA abstracts away the details of the sorting, paging, and handling of these parameters; however, it doesn't seem to gracefully handle these scenarios (i.e. where an invalid sort parameter is specified).
We could add in some additional custom logic to validate that the sort property actually exists on the entity; however, I'm wondering if there is a cleaner more centralized approach for doing this such that we don't lose the benefits and simplicity of the Spring Data JPA abstractions. We use this sorting capability throughout our app with many different entities, so ideally, we'd want more of a generic approach, rather than having to explicitly define or check the sort properties for every entity page requested.
Specifically, we actually extend the PageableArgumentResolver to accept an annotated sort default value that is provided in our controller (not illustrated in the code examples for simplicity), so we'd like to just fallback to this default sort order, or just the default sorting order for the entity, rather than throwing an exception.
Some ideas and attempts.. I could use a QueryCreationListener to intercept the query creation and get the sort parameter; however, I can't actually modify the query at that point. Or, I can extend and use a custom PageableArgumentResolver (we are already doing this) to grab the sort parameters; however, I don't have access to the entity at that point, nor the ability to determine if the entity actually has a property by that name. We could declare the supported properties explicitly; however, again, this defeats the idea of centrally and automatically handling this scenario without requiring specific or declared knowledge of the entities.
Is there any other type of interceptor or similar construct that I can utilize to centrally validate pageable sort parameters and modify if necessary before invoking the query? Or is there any type of configuration or way that Spring can automatically handle this scenario such that it more gracefully handles invalid sort params?
I was taking a look at the code and I think some more of the stack trace would be helpful. But from what I can see, I think there are two places you might want to tackle if you are in the mood to rewrite some Spring code.
There are two scenarios here, in the first one you are passing a sort field that doesn't exist in the object/table. What you really want is for that bad parameter to be silently ignored all the time, not just when passing in a 1PageableArgumentResolver]1. I'm thinking it should be an option on the AbstractQueryCreator (and hence, the JpaQueryCreator) to ignore bad parameters on a sort.
The second part that should be tackled is probably the PageableArgumentResolver. If you pass empty strings or something that doesn't make sense like %20 then it should ignore that parameter and not send it through to the PageRequest.
Happy hacking and good luck. Reading your post has made me realize that my site is vulnerable to the same problem and I really have no good solution.
I think improving the PageableArgumentResolver to gracefully handle those scenarios. It could try to create a PropertyPath instance from the String handed in as Sort and thus make sure it's a valid one. I am a bit torn on whether it makes sense to simply drop the invalid String by default, which would return the result not being sorted at all. This is probably the most seamless experience but might also lead to tedious attempts to find out why the result is not sorted.
However, it. Would be cool if you could raise a JIRA ticket for that against Spring Data Commons and just link this ticket here. Feel free to open a pull request in case you have fleshed out a viable implementation. Thanks for bringing this to the table already!
Anyone know of any other custom spring scopes than Servlet Context Scope and ThreadScope ?
If you've made some closed-source custom scope I'd really also be interested in hearing what it does and how it worked out for you. (I'd imagine someone would make a WindowScope in a desktop app ?)
I'm open to all use cases, I'm looking to expand my horizon here.
We implemented our own custom Spring scope. A lot of our code works at a relatively low level, close to the database, and we maintain a conceptual level on top of that with its own object model of data sources, links, attributes etc.
Anyway, a lot of beans require a so-called StorageDictionary (an encapsulation of this object graph) to do their work. When we make non-trivial changes to the object graph, the dictionary sometimes needs to be blown away and recreated. Consequently, we implemented a custom scope for objects that were dictionary scoped, and part of the invalidation of a given dictionary involves clearing this custom scope. This lets Spring handle a nice form of automatic caching for these objects. You get the same object back every time up until the dictionary is invalidated, at which point you get a new object.
This helps not only with consistency but also allows the objects themselves to cache references to entities within the dictionary, safe within the knowledge that the cache will be valid for as long as they themselves are retrievable by Spring. This in turn lets us build these as immutable objects (so long as they can be wired via constructor injection), which is a very good thing to do anyway wherever possible.
This technique won't work everywhere and does depend heavily on the characteristics of the software (e.g. if the dictionary was modified regularly this would be horribly inefficient, and if it was updated never this would be unnecessary and slightly less efficient than direct access). However, it has definitely helped us pass off this management of lifecycle to Spring in a way that is conceptually straightforward and in my opinion quite elegant.
In my company we've created two custom scopes, one that will use Thread or Request and another that will use either Thread or Session. The idea is that a single scope can be used for scoped beans without having to change configuration based on the execution environment (JUnit or Servlet container). This also really comes in handy for when you run items in Quartz and no longer have a Request or Session scope available.
Background:
I work on a single web app that runs 4 different web sites under the same servlet context. Each site has its own domain name, e.g. www.examplesite1.com, www.examplesite2.com, etc.
Problem:
Sites sometimes require their own customised instance of a bean from the app context (usually for customised display of messages or formatting of objects).
For example, say sites 1 and 2 both use the "standardDateFormatter" bean, site 3 uses the "usDateFormatter" bean and site 4 uses the "ukDateFormatter" bean.
Solution:
I'm planning on using a "site" scope.
We have a Site enum like this:
enum Site {
SITE1, SITE2, SITE3, SITE4;
}
Then we have a filter that stores one of these Site values in the request's thread using a ThreadLocal. This is the site scope's "conversation id".
Then in the app context there'd be a bean named "dateFormatter", with 'scope="site"'. Then, wherever we want to use a date formatter, the correct one for the user's current site will be used.
Added later:
Sample code here:
http://github.com/eliotsykes/spring-site-scope
Oracle Coherence has implemented a datagrid scope for Spring beans. To sum it up:
A Data Grid Bean is a proxy to a
java.io.Serializable Bean instance
that is stored in a non-expiring
Coherence Distributed Cache (called
near-datagridbeans).
Never used them myself but they seem cool.
Apache Orchestra provides SpringConversationScope.
In a Spring Batch application, we have implemented an item scope.
Background
We have lots of #Service components which compute something based on the current batch item. Many of them need the same workflow:
Determine relevant item parts.
Init stuff based on the item.
For each item part, compute something (using stuff).
We moved the workflow into a base class template method, so the subclasses implement only findItemParts(Item) (doing 1 and 2) and computeSomething(ItemPart) (doing 3). So they became stateful (stuff initialized in findItemParts is needed in computeSomething), and that state must be cleared before the next item.
Some of those services also involve injected Spring beans which are also derived from the current item and must be removed afterwards.
Design
We implemented an AbstractScopeRegisteringItemProcessor which registers the item and allows subclasses to register derived beans. At the end of its process method, it removes the item from its scope context, and the derived beans using DefaultSingletonBeanRegistry.destroySingleton.
How it worked out
It works, but has the following problems:
We did not manage to get the derived beans cleaned up without registration (just based on their #Scope). The concrete processor must create and register them.
AbstractScopeRegisteringItemProcessor would have been nicer using composition and dynamically implementing all interfaces of the underlying processor. But then the resulting #StepScope bean is a proxy for the declared return type (i.e. AbstractScopeRegisteringItemProcessor or ItemProcessor) without the required callback interfaces.
EDIT
With the aid of #Eliot Sykes's solution and shared code plus #Cheetah's BeanDefinition registration, I was able to get rid of the registration as singleton beans. Instead, ItemScopeContext (the storage used by both the processor and the Scope implementation; Java-configured via a static #Bean method) implements BeanDefinitionRegistryPostProcessor. It registers a FactoryBean whose getObject() returns the current item or throws an exception if there is none. Now, a #Component annotated with #Scope(scopeName = "Item", proxyMode = ScopedProxyMode.TARGET_CLASS) can simply inject the item and need not be registered for end-of-scope cleanup.
So in the end, it did work out well.
A spring locale scope based on the users locale wihtin a web application
See related wiki page
In my company, we have also implemented spring custom scope. We have a multi tenant system where every customer can customize settings. Instance based scope of ours, caches the beans which are customer specific. So each time user of a customer logs in, these settings are cached and reused again when other users of the same customers sign in.
I once used a kind of conversation scope to store some objects in the session scope, in order to keep them when re-entering the same page, but limited to a single page to avoid to leave useless objects in the session. The implementation just stored the page URL and cleaned the conversation scope on each page change.