Calling static methods in Play! framework controller doesn't work - java

I have a Play! framework with two actions which contain redundant code. So I factored this code into a private static method, but It doesn't work anymore then.
public static void show(long itemId, String listId) {
render(getItem(itemId, listId));
}
private static Item getItem(long itemId, String listId) {
// otherwise duplicate code ...
return item;
}
If I inline the code contained in getItem into the show action everything is fine:
// this works
public static void show(long itemId, String listId) {
Item item = // duplicate code ...
render(item);
}
Why can I not call other static methods within a Play! controller?
Solution
Thanks to 'Codemwnci' I've implemented the following solution:
public static void show(long itemId, String listId) {
renderArgs.put("item", getItem(itemId, listId));
render();
}
I prefer renderArgs because it makes the intention more clear than a local variable.

When you pass a local variable into the render method, the name of the local variable is used when passed through to the Groovy view. In your example, you are not passing a local variable, therefore Play does not know what name to give the item you have specified.
You have a couple of options. You can do either
Set the return from getItem to a local variable (item), and pass item into the view
Set the return from getItem into the renderArgs map, and specify your own name.
Option 1 is probably the most sensible.

Related

How to make code dynamic for similar kind of blocks

I am creating my web page with vaadin where I need to create same kind of blocks for different type for example need to show blocks having car details, so only car name would be different but the block design would be same with same label but different labels. I want to write generic code so that i can expand it for any car name, without adding it manually.
Attaching the code snippet which i am using where i am repeating my code for different type. Want to implement it dynamically.
private Grid<PresentableGenerateInputHeaders> winTSHeaderColumnsGrid;
private Grid<PresentableGenerateInputHeaders> fRHeaderColumnsGrid;
private ListDataProvider<PresentableGenerateInputHeaders> listDataProvider;
private List<PresentableGenerateInputHeaders> presentableGenerateInputHeaders = new ArrayList<>();
private void initWinTsGrid() {
listDataProvider = new ListDataProvider<>(presentableGenerateInputHeaders);
winTSHeaderColumnsGrid = new Grid<PresentableGenerateInputHeaders>(PresentableGenerateInputHeaders.class);
winTSHeaderColumnsGrid.setDataProvider(listDataProvider);
winTSHeaderColumnsGrid.setCaption(i18n.get("view.ruleDetails.general.csvHeaderColumns"));
winTSHeaderColumnsGrid.setStyleName("a-units");
winTSHeaderColumnsGrid.setWidth("450px");
winTSHeaderColumnsGrid.setItems(addGridValues(DataSource.WIN_TS, winTSHeaderColumnsGrid));
winTSHeaderColumnsGrid.getEditor().setEnabled(true);
winTSHeaderColumnsGrid.setColumnOrder("header", "count");
winTSHeaderColumnsGrid.sort("header");
winTSHeaderColumnsGrid.getEditor().addSaveListener((EditorSaveEvent<PresentableGenerateInputHeaders> event) -> {
event.getGrid().select(event.getBean());
selectedGapFillingCountWINTS.add(event.getBean());
});
}
private void initFRGrid() {
listDataProvider = new ListDataProvider<>(presentableGenerateInputHeaders);
fRHeaderColumnsGrid = new Grid<PresentableGenerateInputHeaders>(PresentableGenerateInputHeaders.class);
fRHeaderColumnsGrid.setDataProvider(listDataProvider);
fRHeaderColumnsGrid.setCaption(i18n.get("view.ruleDetails.general.csvHeaderColumns"));
fRHeaderColumnsGrid.setStyleName("a-units");
fRHeaderColumnsGrid.setWidth("450px");
fRHeaderColumnsGrid.setItems(addGridValues(DataSource.FR, fRHeaderColumnsGrid));
fRHeaderColumnsGrid.getEditor().setEnabled(true);
fRHeaderColumnsGrid.setColumnOrder("header", "count");
fRHeaderColumnsGrid.sort("header");
fRHeaderColumnsGrid.getEditor().addSaveListener((EditorSaveEvent<PresentableGenerateInputHeaders> event) -> {
event.getGrid().select(event.getBean());
selectedGapFillingCountFR.add(event.getBean());
});
}
You can change methods to be more generic by identifying all the parts you don't want to keep static, and moving those to be populated by method parameters instead. I.e. instead of
private void myMethod() {
grid.setCaption("myCaption");
}
you would write
private void myMethod(String caption) {
grid.setCaption(caption);
}
and then call it
myMethod("myCaption");
If you need to be outside of the whole class to be able to determine what the real values are, you can for example make the method public or pass on the necessary values in the class constructor.
public MyClass(String gridCaption) {
myMethod(gridCaption);
}
If there are a lot of values you need to set dynamically, you might consider using an object that contains all the necessary values instead.
public void myMethod(MyPojo pojo) {
grid.setCaption(pojo.getGridCaption());
}
In your example it looks like the generic values you want to pass are DataSource dataSource and whatever type of collection selectedGapFillingCountWINTS and selectedGapFillingCountFR happen to be, and the method should probably return the grid rather than set it directly to a class variable.

How to call set before configureFieldMetadata in BridgeClass

I have the following BridgeClass and i need that configureFieldMetadata to be executed after the set method.
But by default it's configureFieldMetadata executed first.
Is it possible ?
Thanks in advance!
public class AdditionalAttributesBridge implements
MetadataProvidingFieldBridge{
#Override
public void set(String name, Object value, Document document,
LuceneOptions luceneOptions) {
Set<AdditionalAttribute> attributes = (Set<AdditionalAttribute>)
value;
for (AdditionalAttribute a : attributes) {
//some code
}
}
#Override
public void configureFieldMetadata(String name, FieldMetadataBuilder
builder) {
//ToDo
}
}
configureFieldMetadata is executed on bootstrap, while set is executed at runtime, when indexing.
So no, this is not possible.
You might want to consider why you need set to be called before configureFieldMetadata. I guess you initialize something in the set method based on the parameters, but I don't know what sort of information you would have in set that you could possibly need in configureFieldMetadata... ?

Pattern for persisting data in Realm?

My issue is how to organize the code. Let say I have a User class
public class User extends RealmObject {
#PrimaryKey
private String id;
#Required
private String name;
public User() { // per requirement of no args constructor
id = UUID.randomUUID().toString();
}
// Assume getter & setter below...
}
and a Util class is needed to handles the save in an asynchronous manner since RealmObjects cannot have methods other than getter/setter.
public class Util {
public static void save(User user, Realm realm) {
RealmAsyncTask transaction = realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
realm.copyToRealm(user); // <====== Argument needs to be declared final in parent method's argument!
}
}, null);
}
}
The intention is to put save() in a Util class to prevent spreading similar save code all over the code-base so that every time I wanted to save I would just call it as such:
User u = new User();
u.setName("Uncle Sam");
Util.save(u, Realm.getDefaultInstance());
Not sure if this affects performance at all, but I was just going to save all fields overwriting what was there except for the unique id field every single time.
The problem is that I now need to set the "user" argument as final in the Util.save() method, which means I cannot pass in the object I need to save other than once.
Is there a different way of handling this? Maybe a different pattern? Or am I looking at this all wrong and should go back to SQLite?
Why is it a problem to set public static void save(final User user, Realm realm) ? It just means you cannot reassign the user variable to something else.
That said, the existence of a save() method can be a potential code smell as you then spread the update behaviour across the code base. I would suggest looking into something like the Repository pattern (http://martinfowler.com/eaaCatalog/repository.html) instead.
Realm is actually working on an example showing how you can combine the Model-View-Presenter architecture with a Repository to encapsulate updates which is a good pattern for what you are trying to do here. You can see the code for it here: https://github.com/realm/realm-java/pull/1960

Data transfer in Android

I'm currently working on a project that has multiple stages to set up a certain thing. In stage one, the user provides a Title, Description, and a required int value. I need to do two things with this data:
Take the title, and set it as the ActionBar title. This is not hard by any means. I've simply set the variable that the Title value was stored in as an extra on the intent, and retrieved it in the new activity, and set it using the .setTitle(); method on the ActionBar.
Here's the one I need help with...
I need to get that integer value transferred over so I can use it as the number returned by the SectionsPagerAdapter, so when it calls getCount(); it returns the value.
I can get the value inside of the same Class as the Title value, but cannot seem to get it in the SectionsPagerAdapter.
Any help is appreciated!
Alternately you can extend SectionsPagerAdapter and include a setter for that value or use a convenience constructor.
Something like this:
public class CustomPagerAdapter extends PagerAdapter {
private int mPageCount;
/**
*
* #param pageCount
*/
public CustomPagerAdapter(int pageCount) {
this.mPageCount = pageCount;
}
#Override
public int getCount() {
return mPageCount;
}
}
I do not know clearly your problem, but before you change page or when you have value, you can use this class:
Class SavedDave extends Application(){
private static String data;
//Contructor
....
public void SetData(String value){
this.data = value;
}
public String getData(){
return data;
}
}
By this class, you can set and get your value every where when application running, is it solve your problem?
Suppose your method in activity is named getTitle();
From adapter call it like context.getTitle();
where context would be one you pass to the constructor of adapter
private final Context context;
public DataPagerAdapter( Context context )
{
this.context = context;
}
Use Shared Preferences. This is the recommended way to do it in Android.
#SharedPref
public interface ExamplePrefs {
// The name will have default value of "Anonymous"
#DefaultString("Anonymous")
String name();
// The field age will have default value 42
#DefaultInt(42)
int age();
// The field address will have default value of "MyAddress"
#DefaultString("MyAddress")
String name();
// The field lastUpdated will have default value 0
long lastUpdated();
}
For your use case just create a class SectionsPagerPref as follows :
#SharedPref
public interface SectionsPagerPref {
#DefaultInt(0)
int getCount();
}

Two methods in same action in struts2?

I am trying to create an action with two methods (JSON action). I am calling them from JSP files. If I try to call an action value as 'medias' in my code, it simply run both the methods every time.
#Action(value="medias", results = {#Result(name="success",type="json")})
public String getMedias(){
System.out.println("IN METHOD CALL medias");
return SUCCESS;
}
#Action(value="allMediaTypes", results = {#Result(name="success",type="json")})
public String getAllMediaTypes(){
System.out.println("IN METHOD CALL allMediaTypes");
return SUCCESS;
}
Both method runs simultaneously, no matter which method is getting called from jsp, it runs both the methods.
Don't prefix your method names with get - doing this has implications.
It's a good idea to name them the same as your action names for consistency, ie:
public String medias() {
...
}
public String allMediaTypes() {
...
}

Categories