Given the following code sample
-- client library code
#FeignClient("string-service")
public interface StringClient {
#RequestMapping(method = RequestMethod.GET, value = "/microservicestring")
public String home();
}
#Service
public class StringHystrixClient {
private final SpringClient springClient;
//....
}
-- service library code
#RestController
public class StringController implements StringClient {
public String home(){
return "World";
}
}
#SpringBootApplication
#EnableHystrix
#EnableEurekaClient
#EnableFeignClients
public class StringApplication { ....}
If the service library references the client library, when the application gets started, through component scanning we will get to a state where in filling the dependencies from StringHystrixClient, the spring container will not know what to do because there are two beans implementing StringClient.
One solution to avoid this would be to not implement the StringClient in the StringController, but the code duplication from the interface and the rest controller would be error prone. Can somebody point out a more elegant solution to this problem?
Is it possible?
Currently I am using some aspects for my MVC controllers, what works really fine. I'm wrapping their responses and I have desired effect.
I also want to do this with Spring Data JPA repositories. But since they're generated based on the interface e.g:
public interface SomeRepository<T extends Some, ID extends Serializable> extends
BaseRepository<T, ID>, JpaSpecificationExecutor<T> {
public List<T> findById(Long id)
}
It generates me controller which is ready to use:
http://localhost:8080/findById?id=1234
I also want to wrap this controller. Is it possible?
This should work:
#Component
#Aspect
public class MyAdvice {
#Before("execution(* com.company.jpa.SomeRepository+.findById(..))")
public void intercept() { ... }
}
Basically, we are telling the framework to intercept the call to the findById method on any sub-class of SomeRepository.
Here is a sample application demonstrating this in action.
I'm using gwt-platform and tried to implement GWT's editor framework. But I don't get it working from within the presenter. There are some answers around the web, that say I have to inject the EditorDriver somehow into the Presenter, but I don't know how to do this...
At the moment I tried this without success:
public class MyPresenter extends Presenter<MyPresenter.MyView, MyPresenter.MyProxy> implements MyUiHandlers {
public interface MyView extends View, HasUiHandlers<MyUiHandlers>, Editor<MyModel> {}
#ProxyStandard
#NameToken(NameTokens.myPage)
#NoGatekeeper
public interface MyProxy extends ProxyPlace<MyPresenter> {}
interface Driver extends SimpleBeanEditorDriver<MyModel, MyView> {}
private Driver editorDriver;
DispatchAsync dispatcher;
#Inject
public MyPresenter(EventBus eventBus, MyView view, MyProxy proxy, DispatchAsync dispatcher) {
super(eventBus, view, proxy);
getView().setUiHandlers(this);
this.dispatcher = dispatcher;
MyModel m = new MyModel();
m.setId(1L);
m.setUsername("username");
m.setPassword("password");
editorDriver = GWT.create(Driver.class);
editorDriver.initialize(this.getView());
editorDriver.edit(m);
}
...
}
It works if I explicitly specify the ViewImplementation, but that's not the way MVP should work:
interface Driver extends SimpleBeanEditorDriver<MyModel, MyViewImpl> {}
...
editorDriver.initialize((MyViewImpl) this.getView());
I would be nice if someone could give me an example how to do it right.
Thanks
An approach similar to what was used in an earlier version of the Expenses sample worked for me:
An interface that the view should implement. The wildcard is used so that the presenter does not need to know the concrete view implementation:
import com.google.gwt.editor.client.Editor;
import com.gwtplatform.mvp.client.View;
/**
* Implemented by views that edit beans.
*
* #param <B> the type of the bean
*/
public interface BeanEditView<B> extends View, Editor<B> {
/**
* #return a new {#link SimpleBeanEditorDriver} initialized to run
* this editor
*/
SimpleBeanEditorDriver<B, ?> createEditorDriver();
}
Your presenter should look something like this now:
public class MyPresenter extends Presenter<MyPresenter.MyView, MyPresenter.MyProxy> implements MyUiHandlers {
public interface MyView extends BeanEditView<MyModel>, HasUiHandlers<MyUiHandlers> {}
#ProxyStandard
#NameToken(NameTokens.myPage)
#NoGatekeeper
public interface MyProxy extends ProxyPlace<MyPresenter> {}
private SimpleBeanEditorDriver<MyModel, ?> editorDriver;
DispatchAsync dispatcher;
#Inject
public MyPresenter(EventBus eventBus, MyView view, MyProxy proxy, DispatchAsync dispatcher) {
super(eventBus, view, proxy);
getView().setUiHandlers(this);
this.dispatcher = dispatcher;
MyModel m = new MyModel();
m.setId(1L);
m.setUsername("username");
m.setPassword("password");
editorDriver = getView().createEditorDriver();
}
...
}
And the view implmementation:
public class MyViewImpl extends ViewWithUiHandlers<MyUiHandlers> implements
MyPresenter.MyView {
public interface Binder extends UiBinder<Widget, MyViewImpl> { }
private static Binder uiBinder = GWT.create(Binder.class);
/**
* The driver to link the proxy bean with the view.
*/
public interface EditorDriver extends SimpleBeanEditorDriver<MyModel, MyViewImpl> { }
private final Widget widget;
public MyViewImpl() {
widget = uiBinder.createAndBindUi(this);
}
#Override
public SimpleBeanEditorDriver<MyModel, ?> createEditorDriver() {
EditorDriver driver = GWT.create(EditorDriver.class);
driver.initialize(this);
return driver;
}
#Override
public Widget asWidget() {
return widget;
}
...
}
That's as close as I could get to MVP with GWT's Editor Framework. I couldn't find a way for the view implementation to NOT know the model but I don't think it's really necessary.
If anyone has any improvements on this, I'm glad to hear.
Found some additional comments on GWT Editors. It seems that it might just not be possible to completely separate the model. As Thomas Broyer puts it in his answer to another Editor question:
"MVP is not set in stone (it's not even defined; it was coined by Martin Fowler but he retired the term in favor of two more specific patterns), so you're only violating the rules you gave to yourself. Put differently, the Editor framework as a whole can be seen as violating MVP: each editor know the model, not necessarily the exact instance it's editing (as with ValueAwareEditor or LeafValue), but at least the kind of objects it's an editor of."
The issue is that the Driver.class passed to GWT.create
editorDriver = GWT.create(Driver.class);
must the concrete class that holds all sub-editors, i.e. all the uibinded widgets.
One solution is the following:
The view interface extends the editor interface for the Model object
public interface MyView extends View, ..., Editor<MyModel>
The view implementation MyViewImpl defines a driver type
interface MyDriverImpl extends SimpleBeanEditorDriver<MyModel,MyViewImpl>
The driver is instantiated in MyViewImpl by
SimpleBeanEditorDriver<MyModel,MyView> driver = GWT.create(MyDriverImpl.class);
The parent type
SimpleBeanEditorDriver<MyModel,MyView>
can be used to pass references of the driver to the presenter
MVP says that you use the presenter to completely seperate the model from the view. In addition I'd say that your approach puts logic inside the view...
I hope that there's another solution ;)
I have declared a generator in my GWT module descriptor and it seems it is not called when the class which trigger the generator is instanciated via the Ginjector.
public interface MyGinjector extends Ginjector {
MyWidget getMyWidget();
}
public class MyEntryPoint implements EntryPoint {
public static final MyGinjector INJECTOR = GWT.create(MyGinjector.class);
public void onModuleLoad() {
MyWidget myWidget = INJECTOR.getMyWidget(); // [1]
MyWidget myWidget = GWT.create(MyWidget.class); // [2]
RootPanel.add(myWidget);
}
}
[1] The generator is not called.
[2] The generator is called.
Does it mean that the GIN injector does not instanciate object through the GWT.create() method?
Thanks for your help.
Kind regards,
AFAIK, GIN (at least up until 1.5) will only generate a GWT.create() if the class has a public zero-arg constructor that is not annotated with #Inject (otherwise it'll do a new on it)
I have my OrganizationRequestContext interface, which works great:
#Service(OrganizationDAO.class)
public interface OrganizationRequestContext extends RequestContext
{
Request<OrganizationProxy> findOrganization(Long id);
InstanceRequest<OrganizationProxy, Void> persist();
InstanceRequest<OrganizationProxy, Void> remove();
}
Now I want to take those last two functions and put them in a PersistentRequestContext of my own design so that I can treat all of my RequestContexts the same in my client code:
public interface PersistableRequestContext<T extends BaseProxy>
{
InstanceRequest<T, Void> persist();
InstanceRequest<T, Void> remove();
}
...
#Service(OrganizationDAO.class)
public interface OrganizationRequestContext extends RequestContext, PersistentRequestContext<OrganizationProxy>
{
Request<OrganizationProxy> findOrganization(Long id);
}
But this fails validation: the server complains that
[ERROR] com.activegrade.shared.data.PersistableRequestContext is not a RequestContext
If I make PersistableRequestContext extend RequestContext, then the server complains that it is not linked to any particular DAO service.
Is there any way to extend a common interface besides RequestContext in my various RequestContext interfaces?
This issue has been fixed in GWT 2.4. Thanks Google!
http://code.google.com/p/google-web-toolkit/issues/detail?id=6035