How to call set before configureFieldMetadata in BridgeClass - java

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... ?

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 return value from this public function?

Examle below must return user.photo_100 (and user.photo_100 response String, I logged it), but var wallPostUserAvatar set null. Looks like I missed something, but I can't find it out.
public class WallPostExtends {
private String wallPostUserAvatar;
public String getUserPhotoLink(int user_id){
//Prepare request for userName and photo
final VKRequest request = VKApi.users().get(VKParameters.from(VKApiConst.USER_ID, user_id, VKApiConst.FIELDS, "photo_100"));
request.executeWithListener(new VKRequest.VKRequestListener() {
#Override
public void onError(VKError error) {
}
#Override
public void onComplete(VKResponse response) {
super.onComplete(response);
//Work with UserName and photo response
VKApiUserFull user = ((VKList<VKApiUserFull>) response.parsedModel).get(0);
wallPostUserAvatar = user.photo_100;
}
});
Log.d("photo link: ", wallPostUserAvatar); //Here is NULL. What am I doing wrong?
return wallPostUserAvatar; //How to return here "user.photo_100" ?
}
}
I think i came to know the reason why wallPostUserAvatar is null , because the you are assigning the value in onComplete() and the execution flow is not how you think, the log you printed will be executed first and then depends on what is happening in executeWithListener() will execute after.
I have a solution for this, i will share with you.
You can use callback mechanism here.
A typical example would be using Interface
public interface Callbacks {
public void successCallback(String response);
public void failCallback(String response);
}
Then you can use this interface as follows:
public void getUserPhotoLink(int user_id,final Callbacks callback){
request.executeWithListener(new VKRequest.VKRequestListener() {
#Override
public void onError(VKError error) {
callbacks.failCallback("fail");
}
#Override
public void onComplete(VKResponse response) {
super.onComplete(response);
//Your code
callback.successCallback(user.photo_100);
}
Then you can call you function getUserPhotoLink() as
getUserPhotoLink(userid value,new Callbacks() {
#Override
public void successCallback(String success) {
//You will get your desired result here
}
#Override
public void failCallback(String fail) {
});
Hope it will help you
I don't know the VKApi, but it looks like its an asynchronous call based on the name and the fact you pass in a listener. That means you CANT return the string, because you won't have it until the asynchronous call completes. Instead you'd need to do any processing of it in onComplete.
In short:
Sorry to tell you, but you cannot return any value right there.
The VKRequestListener is called asynchronously, while the method returns immediately.
You will have to find a more suitable solution for this, like handing over the object you want to make the String accessable to and call a set-Method in the onComplete block.
If this is not being run on the UI thread, try putting a while(wallPostUserAvatar!=null); after the call to the log function. This would work because, as is, you probably have a race condition between the return and the API request and the return statement will almost always win that race.

How to enforce that only a given module in my app can change properties in my object?

I have a class which has a State property. When instantiated, this property contains the current state of the object. The states have a well defined flow (example: from state 1 you can only go to states 2 and 3. From 2 you can only go to 4 and so on...), so I intent to create a module in my system that will manage these changes.
Ideally it would receive the object and the action performed and it would set the new state.
I am aware how to do that, but I am missing the point: how can I force everyone to use this module to change the state? I don't want anybody else changing the state, only this module.
Is there a design pattern or OO "trick" I could use?
I don't know if this is useful, but I am using JAVA EE6.
out of the top of my head:
class A {
protected State state
public State getState(){ return state; }
}
class B extends A {
public void setState( State s ){ this.state = s }
}
so the property remains read-only for all users of class A, but writable if you cast the instance to B.
UPDATE:
to use the callback-mechanismus:
interface StateChanger(){
public void call( State state );
}
class A {
protected State state
public State getState(){ return state; }
public void setState( StateChanger stateChanger ){
stateChanger.call( state );
}
}
then you can use it as:
classAInstance.setState( new StateChanger(){
#Override
public void call( State state ){
//do stuff
}
} );
Perhaps you need to include in the StateChanger.call() also the this as a parameter
in dynamic languages like Groovy it looks really compact
You simply use package access visibility for your mutators/setters and put the instance to be secured in the same package with the classes in the module that can change it.
Example:
package com.bla.bla.bla.models;
public class ProtectedData {
private String protectedField;
public String getProtectedField() {
return protectedField;
}
void setProtectedField(String newValue) {//package visibility
this.protectedField = newValue;
}
}
package com.bla.bla.bla.models;//the same package (no matter the name)
public class ProtectedWorkflowController {
public void closeProtectedData(ProtectedData data) {
data.setProtectedField(null);
}
}
PS: the notion of module is undefined in Java, so I consider it is not wrong considering module==package in your case.

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

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.

Delegation Event Model pattern Java

When applying this pattern Delegation Event Model, is it correct to put ALL the code in the fire... methods and pass the parameters from the public method?
Like this
public void addBananas(Banana banana) {
fireBananaAdded(banana);
}
private void fireBananaAdded(Banana banana) {
//Create event etc and add banana to list here
}
Or should I have the add to list part in this example in the addBananas method instead? Because if I do it this way I will not have the opportunity to "attach" the banana object to the event-object which will be passed to the listeners, right?
I would put as much logic in addBanana() that is related to actually adding the Banana as I can.
When I'm done with addBanana(), I would call fireBananaAdded() which would generate the appropriate BananaAddedEvent and send it to the BananaAddedListeners (or just BananaListeners, which ever you have.)
To put the ADD logic in the FIRE method is simply, well, BANANAS!
public void addBananas(Banana banana) {
if(BananaHolder.hasRoom()) {
BananaHolder.add(banana);
fireBananaAdded(banana);
}
}
private void fireBananaAdded(Banana banana) {
BananaAddedEvent event = new BananaAddedEvent(banana);
for(BananaListener listener : listenersByType(Banana.class)) {
listener.bananaAdded(event);
}
}

Categories