tomasbilek / gwteventservice

Automatically exported from code.google.com/p/gwteventservice
Other
0 stars 0 forks source link

Does the GWTEventService can be defined as GWTRPC-Spring Remote service to use dependency injection #26

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
Does the gwteventservice can be defined as GWTRPC-Spring remote service?

The gwtrpc-spring allows for simple integration of Spring and GWT 1.6. Instead 
of having a separate servlet for each service there is one RemoteServiceServlet 
that looks the configured SpringContext for a instance of a class that 
implements the Remote Service. So that means your services don't have to 
inherit RemoteServiceServlet just implement your RemoteService interface. That 
means any Spring POJO can become a Gwt RPC Service.

In our application architecture we are using heavly spring dependency injection 
with GWTRPC-Spring as RemoteService. I was looking for a solution to use the 
GWTEventService to be integrated as dependency injection. While going through 
the demo sample it looks the "/<your-GWT-module-path>/gwteventservice mapping 
url for the EventServiceImpl cannot be changed. In the demo sample if i change 
the URL link "/<your-GWT-module-path>/gwteventservice.rpc then GWTEventService 
does not work and we get output as Output:
[ERROR] Client-Error: Error on register client for domain!.

I would like to define the EventServiceImpl invoked as GWTRPC-Spring dependency 
injection. For example below:

<servlet>
                 <servlet-name>dispatcher</servlet-name>                 <servlet-class>                         org.gwtrpcspring.RemoteServiceDispatcher                 </servlet-class>         </servlet>

<servlet-mapping>                 <servlet-name>dispatcher</servlet-name>       
          <url-pattern>*.rpc</url-pattern>         </servlet-mapping>

@RemoteServiceRelativePath"/<your-GWT-module-path>/gwteventservice.rpc")
interface MyService implements EventService, RemoteService

class MyEventServiceImpl extends 
de.novanic.eventservice.service.EventServiceImpl implements EventService

Does "/<your-GWT-module-path>/gwteventservice servlet mapping can be defined as 
"/<your-GWT-module-path>/gwteventservice.rpc in order to make the 
EventServiceImpl as a Spring dependency injection implementation integrated as 
GWTRPC-Spring?

Original issue reported on code.google.com by leogem0...@gmail.com on 19 Sep 2010 at 1:12

GoogleCodeExporter commented 8 years ago
Hi,

Issue25 describes a similar problem 
(http://code.google.com/p/gwteventservice/issues/detail?id=25) and I think the 
first step to solve it is to get rid of the "hard" module-base mapping which is 
described in Issue22 
(http://code.google.com/p/gwteventservice/issues/detail?id=22). That means 
Issue22 has to be solved at first.

The code snippet of Issue22 shows the client side mapping to access the 
RemoteService (GWT.getModuleBaseURL() is used). Could you please tell me how 
you access the RemoteService in your application? I think you won't use 
GWT.getModuleBaseURL().

Thanks in advance.

Sven S.

Original comment by sven.strohschein@googlemail.com on 19 Sep 2010 at 2:01

GoogleCodeExporter commented 8 years ago
Hi Sven,

Thanks for your response.

You are correct we are not looking to use GWT.getModuleBaseURL().

As i explained earlier we are using GWTRPC-Spring 
(http://code.google.com/p/gwtrpc-spring/) to inject our GWT service 
implementation classes as Spring beans for our POJOS.

So that means your services don't have to inherit RemoteServiceServlet just 
implement your RemoteService interface. That means any Spring POJO can become a 
Gwt RPC Service.

1) Can we make the gwteventservice mapping URL to be mapped to any URL such as 
/apps/test/myservice.rpc instead of hard coding to 
/<gwtmodulepath>/gwteventservice in web.xml?

2) Also in all the gwteventservice demos it looks like you have to create a 
package name de.novanic.eventservice.service in your project to create the 
EventServiceImpl class as a RemoteServiceServlet for registering the domains. 
Is there a way instead of hardcoding the package name 
(de.novanic.eventservice.service ) in your project it can be any package name 
for the implementation of the EventServiceImpl class.

Original comment by leogem0...@gmail.com on 21 Sep 2010 at 1:38

GoogleCodeExporter commented 8 years ago
Hi Sven,

Please ignore my 2) suggestion as I am able to create my own package and 
implement my own MyEventServiceImpl.

Currently the only limitation of the gwteventservice is /gwteventservice 
mapping URL in web.xml and secondly the EventServiceImpl uses the GWT 
RemoteServiceServlet instead of integrated with GWTRPC-Spring to implement 
RemoteService interface and use the dependency injection to be invoked instead 
of declaring as servlet in web.xml

Original comment by leogem0...@gmail.com on 21 Sep 2010 at 8:17

GoogleCodeExporter commented 8 years ago
Hi,

to implement the RemoteService interface isn't a problem, but I still haven't 
found a mapping which works for both worlds (till yet). To use 
GWT#getModuleBase() seems to be the common way, but isn't compatible with 
GWT-RPC-Spring. I will set up a GWT-RPC-Spring project in the next days to find 
a working solution.

Original comment by sven.strohschein@googlemail.com on 22 Sep 2010 at 6:00

GoogleCodeExporter commented 8 years ago
Hi Sven,

Thanks for your response.

It will be really great if we can find a solution of calling GWTEventService 
with GWTRPC-Spring.

As for now due to the hardcoded /gwteventservice URL mapping in the web.xml for 
the EventServiceImpl class I cannot find any way to call the GWTEventService 
with our current GWTRPC-Spring RemoteService implementation. I alsi tried to 
create a Spring Controller with @Controller annotation to inject dependency 
injection for EventServiceImpl class so that I do not have to create the 
mapping in web.xml for EventServiceImpl but when i gave the @RequestMapping for 
the Spring controller to be /test/gwteventservice.do it did not worked and gave 
me exception as Error in registering the client code.

We definately need the solution with GWTRPC-Spring to create a RemoteService 
for EventServiceImpl class so that we do not have to define the 
EventServiceImpl class in the web.xml with /gwteventservice as the hardcoded 
URL.

Below is the implementation i was looking for calling EventServiceImpl as a 
GWTRPC_Spring service instead of defining it in web.xml.

1) Setting for web.xml

<servlet>
        <servlet-name>gwtDispatcher</servlet-name>
        <servlet-class>org.gwtrpcspring.RemoteServiceDispatcher</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>gwtDispatcher</servlet-name>
        <url-pattern>*.rpc</url-pattern>
    </servlet-mapping>

2) EventServiceRemoteService

@RemoteServiceRelativePath("/apps/test/gwteventservice.rpc")
public interface EventServiceRemoteService extends RemoteService,EventService {

    /**
     * Utility/Convenience class.
     * Use EventServiceRemoteService.App.getInstance() to access static instance of EventServiceRemoteServiceAsync
     */
    public static class App {
        private static final EventServiceRemoteServiceAsync ourInstance;

        static {
            ourInstance = (EventServiceRemoteServiceAsync) GWT.create(EventServiceRemoteService.class);
        }

        public static EventServiceRemoteServiceAsync getInstance() {
            return ourInstance;
        }
    }

    public void initEventService();
}

3) EventServiceRemoteServiceAsync

public interface EventServiceAppRemoteServiceAsync extends EventServiceAsync {

    void initEventService(AsyncCallback<Void> async);
}

4) EventServiceRemoteServiceImpl implementation class as Spring Service

@Service
public class EventServiceRemoteServiceImpl implements EventServiceRemoteService 
{

    private static final ServerLogger LOG = ServerLoggerFactory.getServerLogger(EventServiceRemoteServiceImpl.class.getName());

    private EventRegistry myEventRegistry;

    /**
     * Initializes the {@link de.novanic.eventservice.client.event.service.EventService}.
     */
    public void initEventService() {
        myEventRegistry = initEventRegistry();
        final String theClientId = getClientId(true);
        LOG.debug("Client \"" + theClientId + "\" initialized.");
    }

    /**
     * Register listen for a domain.
     *
     * @param aDomain domain to listen to
     */
    public void register(Domain aDomain) {
        register(aDomain, null);
    }

    /**
     * Register listen for a domain.
     *
     * @param aDomain       domain to listen to
     * @param anEventFilter EventFilter to filter events
     */
    public void register(Domain aDomain, EventFilter anEventFilter) {
        final String theClientId = getClientId();

        myEventRegistry.registerUser(aDomain, theClientId, anEventFilter);
    }

    /**
     * Register listen for a domain.
     *
     * @param aDomains domains to listen to
     */
    public void register(Set<Domain> aDomains) {
        for (Domain aDomain : aDomains) {
            register(aDomain);
        }
    }

    /**
     * Register listen for domains.
     *
     * @param aDomains      domains to listen to
     * @param anEventFilter EventFilter to filter events (applied to all domains)
     */
    public void register(Set<Domain> aDomains, EventFilter anEventFilter) {
        for (Domain aDomain : aDomains) {
            register(aDomain, anEventFilter);
        }
    }

    /**
     * Registers an {@link de.novanic.eventservice.client.event.listener.unlisten.UnlistenEvent} which is triggered on a
     * timeout or when a user/client leaves a {@link de.novanic.eventservice.client.event.domain.Domain}. An
     * {@link de.novanic.eventservice.client.event.listener.unlisten.UnlistenEvent} is hold at the server side and can
     * contain custom data. Other users/clients can use the custom data when the event is for example triggered by a timeout.
     *
     * @param anUnlistenScope scope of the unlisten events to receive
     * @param anUnlistenEvent {@link de.novanic.eventservice.client.event.listener.unlisten.UnlistenEvent} which should
     *                        be transferred to other users/clients when a timeout occurs or a domain is leaved.
     */
    public void registerUnlistenEvent(UnlistenEventListener.Scope anUnlistenScope, UnlistenEvent anUnlistenEvent) {
        final String theClientId = getClientId();
        myEventRegistry.registerUnlistenEvent(theClientId, anUnlistenScope, anUnlistenEvent);
    }

    /**
     * Registers an {@link EventFilter} for the domain.
     *
     * @param aDomain       domain to register the EventFilter to
     * @param anEventFilter EventFilter to filter events for the domain
     */
    public void registerEventFilter(Domain aDomain, EventFilter anEventFilter) {
        final String theClientId = getClientId();
        myEventRegistry.setEventFilter(aDomain, theClientId, anEventFilter);
    }

    /**
     * Deregisters the {@link EventFilter} of the domain.
     *
     * @param aDomain domain to drop the EventFilters from
     */
    public void deregisterEventFilter(Domain aDomain) {
        final String theClientId = getClientId();
        myEventRegistry.removeEventFilter(aDomain, theClientId);
    }

    /**
     * Returns the EventFilter for the user domain combination.
     *
     * @param aDomain domain
     * @return EventFilter for the domain
     */
    public EventFilter getEventFilter(Domain aDomain) {
        final String theClientId = getClientId();
        return myEventRegistry.getEventFilter(aDomain, theClientId);
    }

    /**
     * The listen method returns all events for the user (events for all domains where the user is registered and user
     * specific events). If no events are available, the method waits a defined time before the events are returned.
     * The client side calls the method with a defined interval to receive all events. If the client don't call the
     * method in the interval, the user will be removed from the EventRegistry. The timeout time and the waiting time
     * can be configured with {@link de.novanic.eventservice.config.EventServiceConfiguration}.
     *
     * @return list of events
     */
    public List<DomainEvent> listen() {
        final String theClientId = getClientId();
        LOG.debug("Listen (client id \"" + theClientId + "\").");
        return myEventRegistry.listen(theClientId);
    }

    /**
     * Unlisten for events (for the current user) in all domains (deregisters the user from all domains).
     */
    public void unlisten() {
        final String theClientId = getClientId();
        LOG.debug("Unlisten (client id \"" + theClientId + "\").");
        myEventRegistry.unlisten(theClientId);
        LOG.debug("Unlisten finished (client id \"" + theClientId + "\").");
    }

    /**
     * Unlisten for events (for the current user) in the domain and deregisters the user from the domain.
     *
     * @param aDomain domain to unlisten
     */
    public void unlisten(Domain aDomain) {
        final String theClientId = getClientId();
        LOG.debug("Unlisten (client id \"" + theClientId + "\").");
        myEventRegistry.unlisten(aDomain, theClientId);
        LOG.debug("Unlisten finished (client id \"" + theClientId + "\").");
    }

    /**
     * Unlisten for events (for the current user) in the domains and deregisters the user from the domains.
     *
     * @param aDomains set of domains to unlisten
     */
    public void unlisten(Set<Domain> aDomains) {
        for (Domain theDomain : aDomains) {
            unlisten(theDomain);
        }
    }

    /**
     * Checks if the user is registered for event listening.
     *
     * @param aDomain domain to check
     * @return true when the user is registered for listening, otherwise false
     */
    public boolean isUserRegistered(Domain aDomain) {
        final String theClientId = getClientId();
        return myEventRegistry.isUserRegistered(aDomain, theClientId);
    }

    /**
     * Adds an event for all users in the domain.
     *
     * @param aDomain domain to add the event
     * @param anEvent event to add
     */
    public void addEvent(Domain aDomain, Event anEvent) {
        myEventRegistry.addEvent(aDomain, anEvent);
    }

    /**
     * Adds an event only for the current user.
     *
     * @param anEvent event to add to the user
     */
    public void addEventUserSpecific(Event anEvent) {
        final String theClientId = getClientId();
        myEventRegistry.addEventUserSpecific(theClientId, anEvent);
    }

    /**
     * Returns the domain names, where the user is listening to
     *
     * @return collection of domain names
     */
    public Set<Domain> getActiveListenDomains() {
        final String theClientId = getClientId();
        return myEventRegistry.getListenDomains(theClientId);
    }

    /**
     * Registers the {@link de.novanic.eventservice.config.loader.WebDescriptorConfigurationLoader},
     * loads the first available configuration (with {@link de.novanic.eventservice.config.EventServiceConfigurationFactory})
     * and initializes the {@link de.novanic.eventservice.service.registry.EventRegistry}.
     *
     * @param aConfig servlet configuration
     * @return initialized {@link de.novanic.eventservice.service.registry.EventRegistry}
     */
    private EventRegistry initEventRegistry(ServletConfig aConfig) {
        final WebDescriptorConfigurationLoader theWebDescriptorConfigurationLoader = new WebDescriptorConfigurationLoader(aConfig);
        final EventServiceConfigurationFactory theEventServiceConfigurationFactory = EventServiceConfigurationFactory.getInstance();
        theEventServiceConfigurationFactory.addConfigurationLoader(ConfigLevelFactory.DEFAULT, theWebDescriptorConfigurationLoader);

        final EventRegistryFactory theEventRegistryFactory = EventRegistryFactory.getInstance();
        EventRegistry theEventRegistry = theEventRegistryFactory.getEventRegistry();

        if (theWebDescriptorConfigurationLoader.isAvailable()) {
            theEventServiceConfigurationFactory.loadEventServiceConfiguration();
        }
        return theEventRegistry;
    }

     private EventRegistry initEventRegistry() {
        //final WebDescriptorConfigurationLoader theWebDescriptorConfigurationLoader = new WebDescriptorConfigurationLoader(aConfig);
        final EventServiceConfigurationFactory theEventServiceConfigurationFactory = EventServiceConfigurationFactory.getInstance();
        //theEventServiceConfigurationFactory.addConfigurationLoader(ConfigLevelFactory.DEFAULT, theWebDescriptorConfigurationLoader);

        final EventRegistryFactory theEventRegistryFactory = EventRegistryFactory.getInstance();
        EventRegistry theEventRegistry = theEventRegistryFactory.getEventRegistry();

        //if (theWebDescriptorConfigurationLoader.isAvailable()) {
          //  theEventServiceConfigurationFactory.loadEventServiceConfiguration();
        //}
        return theEventRegistry;
    }

    /**
     * Returns the client id.
     *
     * @return client id
     */
    private String getClientId() {
        return getClientId(false);
    }

    /**
     * Returns the client id.
     *
     * @param isInitSession initializes the session (if not already initialized).
     * @return client id
     */
    protected String getClientId(boolean isInitSession) {
        return RemoteServiceUtil.getThreadLocalRequest().getSession(isInitSession).getId();

    }
5) Client side calling the EventServiceRemoteService service

EventServiceRemoteService.App.getInstance().initEventService(new 
VoidAsyncCallback());

Original comment by leogem0...@gmail.com on 23 Sep 2010 at 3:27

GoogleCodeExporter commented 8 years ago
Hi Sven,

Did you get a chance to look into integration of GWTEventService with 
GWTRPC-Spring for making GWTEventService to use Spring dependency injection?

Thanks

Original comment by leogem0...@gmail.com on 28 Sep 2010 at 6:42

GoogleCodeExporter commented 8 years ago
Hi,

I had no time to setup a GWT-RPC-Spring project to test if it works, but I have 
removed GWT#getModuleBaseURL() and replaced it with the 
RemoteServiceRelativePath annotation. It is already in the trunk version (since 
today). The RemoteService interface is implemented via the EventService 
interface.

Could you please try if it helps to setup the mapping for your Spring project?

Thanks in advance.

Regards,

Sven S.

Original comment by sven.strohschein@googlemail.com on 28 Sep 2010 at 8:48

GoogleCodeExporter commented 8 years ago
Hi Sven,

Does it help to provide our own implementation of the EventServiceImpl class 
and provide the servlet mapping as /myservice.rpc which could understood by 
gwtdispatcher for GWTRPC-Spring integration?

How from the client side we can invoke our own implementation of the 
EventServiceImpl when someone adds the event on the server side with 
GWTEventService?

Can we igonore the current deployment of providing EventServiceImpl mapping in 
the web.xml and provide our own implementation?

Thanks.

Original comment by leogem0...@gmail.com on 28 Sep 2010 at 9:19

GoogleCodeExporter commented 8 years ago
Hi,

have you tried it with my last trunk commits which I have described above 
(Comment 7)?

Your suggestion should also work. We could extract the EventService 
creation/instantiation as a factory (that is definitely a good idea) and you 
can overwrite the instantiation with your own implementation of EventService. 
Your implementation should easily be able to work like in the following code 
snippets. After that you can map and create/access it without any limitations.

public class EventServiceSpringImpl extends EventServiceImpl implements 
EventServiceSpring {}

public interface EventServiceSpring extends EventService {}

public interface EventServiceSpringAsync { ... }

Regards

Sven S.

Original comment by sven.strohschein@googlemail.com on 3 Oct 2010 at 8:03

GoogleCodeExporter commented 8 years ago
Oh, I forget to say that the handling of your service would work automatically 
in GWTEventService when your service interface is castable to the EventService 
interface (should work with the code snippets above). You can use the 
GWTEventService-API as common and don't have to access your service manually. 
All you have to do is to provide your service interfaces (code snippet above) 
and to implement your factory method like

public EventService createEventService() {
  return GWT.create(EventServiceSpringImpl.class);
}.

I will start to implement the factory next week.

Regards,

Sven S.

Original comment by sven.strohschein@googlemail.com on 3 Oct 2010 at 8:16

GoogleCodeExporter commented 8 years ago
Hi Sven,

Thanks for your response.

Exactly i am looking for something similar where GWTEventService can be mapped 
and creation/access as our own implementation. It would be really great if you 
can provide the GWTEventService as a factory.

I would appreciate if you could also provide a sample code snippet as How to 
map and create/ and how to instantiate our own implementation of 
GWTEventService with an example as it can save a lot of time to test the same. 
When does we have to call the factory method from the client side.

As i want to know once the GWTEventService is available as Factory then How to 
invoke our own EventServiceImpl class on the server side. Do i need to call my 
implementation of EventService from the client side similar like i am calling 
my other services which will be a Http POST request to my service mapping URL 
/apps/test/gwteventservice.rpc by using 
@RemoteServiceRelativePath("/apps/test/gwteventservice.rpc")annotation mapping 
on my implementation of the EventService interface.

For example as i have sent earlier the code snippet.

Client side calling the EventServiceRemoteService service

EventServiceRemoteService.App.getInstance().initGWTEventService(new 
VoidAsyncCallback());

Thanks.

Original comment by leogem0...@gmail.com on 5 Oct 2010 at 3:36

GoogleCodeExporter commented 8 years ago
Hi,

I have now committed all changes to create individual mappings and 
instantiations of EventService. All you have to do is to write a 
EventServiceCreator (new interface). The EventServiceCreator is called from 
GWTEventService to create an instance of EventService. Here you can write your 
logic to create an instance of EventService with GWT-RPC-Spring. You can take a 
look at DefaultEventServiceCreator to see working implementation.

To let GWTEventService use your written EventServiceCreator, you have to get 
the RemoteEventService with 
RemoteEventServiceFactory#getInstance()#getRemoteEventService(<your-EventService
Creator>);.

Here are some code-snippets for a possible implementation.

public class EventServiceSpringImpl extends EventServiceImpl implements 
EventServiceSpring {}

public interface EventServiceSpring extends EventService {}

public interface EventServiceSpringAsync { /*...*/ }

public class EventServiceSpringCreator implements EventServiceCreator {
  public EventServiceAsync createEventService() {
    return MagicGWTRPCSpringCreator.get(EventServiceSpring.class); // ;-)
  }
}

With this solution you can define EventService like every other GWT-RPC-Spring 
service. Please let me know if you need support regarding this solution and 
whether it fulfills your expectations.

Regards,

Sven S.

Original comment by sven.strohschein@googlemail.com on 19 Oct 2010 at 10:06

GoogleCodeExporter commented 8 years ago
Hi Sven,

Thank you for the update.

I will look into the DefaultEventServiceCreator implementation provided by you 
and will test to create my own GWTRPC-Spring Event Service mapping and 
instantiation.

Could you please provide a client side sample code as How to invoke this new 
mapping instantiation?

Thanks. 

Original comment by leogem0...@gmail.com on 20 Oct 2010 at 3:57

GoogleCodeExporter commented 8 years ago
Hi Sven,

Just wanted to add to my previous response.

If you can provide a client side Demo example code as when to invoke this new 
EventServiceImpl instantiation. Similar like you provided a Demo application as 
pushing the "Hello Message" from the server side.

I just need to know as on the client side when we have to invoke our new 
EventServiceCreator.

RemoteEventServiceFactory#getInstance()#getRemoteEventService(<your-EventService
Creator>);.

Thanks.

Original comment by leogem0...@gmail.com on 20 Oct 2010 at 4:03