I need a method which is executed before an action is triggered to do some initialization, to get a list of rows from database to display it in a tabular form.
I can think of using the prepare() method but the list retrieved from the database is dependent upon the current page number supplied dynamically (especially while deleting and editing rows displayed in an HTML table. On page load, the current page would be 1 by default, of course).
Therefore, the current page supplied via either a hidden field or a query-string parameter would not be available in the prepare() method, since it is executed early before request parameters are bound to the action.
Another way I can think of is by using a method annotated by #Before but this method is not executed, if any conversion/validation error(s) occur(s).
Can we have a method which is guaranteed to be executed before (or after) an action is executed and it can also have access to request parameters which is not the case with the prepare() method?
Currently, I'm using a method annotated by #Before. This requires some ugly conditional checks before getting rows from the database like
if(hasErrors() && CollectionUtils.isEmpty(list)) in the getter method of the list so that in case conversion/validation error(s) occur(s), the list can be initialized in this getter method instead of being initialized in the method annotated by #Before which is in fact not going to be executed because of conversion/validation error(s).
Related
I'm using Hibernate 3 and Grails 2.2.5.
I have an AJAX call in one of my views that is supposed to look up some data and provide a text result. In the methods used to generate the text result, I have a method call to a service to save the text result to its own domain.
The problem is that the .save(flush: true) will not persist to the database. However, if I add a Groovy SQL instance and perform an .executeInsert() with any insertion the insert in the Groovy SQL will be inserted AND the .save(flush: true) method will work as expected... I've tried various different ways, but as soon as I comment out the .executeInsert("...") the domain class will not be persisted.
I've checked common problems: validation checks out (returns true), I turned deepValidate to false and I used flush in case Hibernate was trying to save the insertion statement to a later time. I also turned on logSql = true in DataSource.groovy and the SQL insert statement does get logged when I comment the .executeInsert("...") out but is never persisted to the table.
-EDIT/UPDATE-
The Hibernate log has the insert statement as:
insert into TextDomain (version, text, ... , id) values (?,?,?,?,?)
Are the question marks supposed to be there? Not too experienced with Hibernate so I'm not sure if that's the actual SQL statement it is executing or if it is filling the values in?
Also, the method I'm trying to call .save() in is in src/groovy .
EDIT/UPDATE -> TEST:
I setup a test as a single action in a controller. I simply called a service method that filled the textDomain with some test values and then did a .save(). When calling the controller action (i.e. going to the url my-app:8080/test/text) the textDomain is persisted correctly. However, I tried adding the service that has the actual textDomain instantiation and test values from another service and it will not persist...
I have a JSF/PrimeFaces web application. In one page <p:dataTable> and <p:fileDownload> components are been used. The bean constructor loads the data from the DB. It works fine when the page loads. The download button is provided in the last column of the datatable. When this button is clicked, then it is going to file download controller and everything works fine.
But if I add a search function to the page which filters the datatable results based on the query, then clicking the download button doesn't return the downloaded file, instead it just refreshes the page.
How is this caused and how can I solve it?
That can happen if the model behind the value of the <p:dataTable> has incompatibly changed between the request of displaying the table with the search results and the request of downloading the file. That can in turn happen if your bean is request scoped. The model is then newly created on every single HTTP request. During the form submit request, JSF needs to iterate over the model while finding and executing actions in the datatable. However, if the model does not represent the same model as it was when the form is displayed, then this will all fail.
Placing the bean in the view scope should fix the problem, provided that you're properly initializing the model in the (post)constructor and changing it in the (action)listener methods and thus not in any getter method. A view scoped bean instance lives as long as you're postbacking to the same view and hence the model isn't reinitialized on every request anymore, but just the same one will be reused across requests on the same view.
Or, if you really need to keep the bean in the request scope for technical reasons, then you need to ensure that you pass the search query as request parameter as well, so that the model can properly be initialized based on the search query.
I believe that if both - xml validation, and validation in the action class are setup, then, irrespective of whether errors were discovered in the xml validation phase, the action class' validate method will be called. Building on this premise, how can I know that there were any xml validation errors from inside my action's validate() method (getActionErrors().size() == 0.. something like that).
My purpose is to set certain variables of the action class if there were validation errors before sending control back to the jsp. (setting them inside prepare would be wrong, as prepare would execute irrespective of whether there were errors)
You can use getFieldErrors() which returns
Map with errors mapped from fieldname (String) to Collection of String
error messages
There are also helper methods such as hasActionErrors() and hasFieldErrors() which will help you determine if errors already exist.
Note that the first tells you if there are Action-level errors and the latter helps determine if there are specific, field associated errors.
I have a dropdown in my form that has a problem to populate when validation failed. I use xml validation with Preparable interface. To access data for dropdown I need to pass some ID from the form. The problem is when validation failed and prepare()/prepareInput() called, none of the variables in class including ID is set. ID is hidden parameter in the form that does not change. Please advice.
Thank you,
Yuri
prepare() in struts2 is rather synonymous with the role of init() in many other frameworks, that is it is called to initialise the action and fills a role very similar to the constructor.
There seems to be something missing... using the default-stack all the parameters on the action should have been set before validation is called. So if the client is indeed passing in the parameters I can not see why or how any would be missing unless some part of your logic clears them.
Sometimes it is necessary to acquire other objects as fields in your action derived from the values set by a form, or otherwise passed in as parameters. In this case you would like prepare to be called after values are set and then validate, if this scenario applies to you then the params-prepare-params stack is appropriate.
Personally, I would put preparation logic into the actions execute method rather than the prepare method. It is only when I put multiple actions into a single class that the prepare method is most appropriate as it factors out what would be repetition. Then the params-prepare-params is a special case that can crop up although I would argue the if you use DI it may never need to be used.
If this is not helpful please expand your question with the action class/xml mapping(if any) and provide the validation xml as well so we can see why this would be happening.
I want to create a lazy-loaded property that returns a collection on a Model, how do I do this?
I don't want to create an association for this.
So I want it to return a collection, if the collection hasn't been initialized yet then hit the database, return the rows, then initialize it.
If it get's run once, then no need to run it again since the next page request will start things over.
Add an instance attribute (e.g. #my_attribute)
And then define
def my_attribute
#my_attribute ||= initialize_my_attribute
end
(Note: initialize_my_attribute is a function/method you've implemented that will load the value you want.)
How this works: the attribute starts out with a nil value (we haven't assigned anything to it). The object instance can't access it directly, because we haven't defined an attribute accessor on it. Instead we have a method that has the exact same name as the attribute, so that when you call my_object.my_attribute it looks exactly as if you're accessing the attribute when you're actually calling the object instance's method.
What happens in the method? The ||= short hand is equivalent to
#my_attribute = (#my_attribute || initialize_my_attribute)
So if #my_attribute already has value, that value is returned. Otherwise, #my_attribute gets a value assigned (and then returned). In other words: the value will be loaded in #my_attribute the first time it is accessed (and only the first time).
And voila! Lazy loading.
Associated properties are lazy-loaded by default. Check your logs so see that queries to the database are only done if the property is accessed.
I ran into this issue too. And after I implemented my self-made lazy-loading functions I realised that they were meaningless. By adding lazy-loaders like described above, you add a lazy-loader to the internal lazy-loader which makes things slower in terms of performance without adding any value.