GWT polymorphic lists with #ExtraTypes - gwt

I have a little problem with a list that contains different types of elements and i would like to see if anyone of you have met the problem before. The issue should be solved with the use of #ExtraTypes, but it is not working for me, so i guess i am not using it correctly. So, the scenario is (bean names are changed for clarity):
GENERAL:
I am using GWT 2.5 with RequestFactory.
SERVER-SIDE:
I have a RootBean that contains, among other stuff, a List <ChildBean>.
This ChildBean contains some primitive attributes.
ChildBean is also extended by a MoreSpecificChildBean that inherits all the parent attributes and adds a few more.
The RootBean gets its list filled up with elements of type ChildBean and MoreSpecificChildBean depending on some logic.
CLIENT-SIDE:
IRootBeanProxy is a ValueProxy with these annotations:
#ProxyFor (value = RootBean.class)
#ExtraTypes ({IMoreSpecificChildBeanProxy.class})
and contains a list
List <IChildBeanProxy> getChildren ();
IChildBeanProxy is a ValueProxy:
#ProxyFor (value=ChildBean)
public interface IChildBeanProxy extends ValueProxy
IMoreSpecificChildBeanProxy is a ValueProxy:
#ProxyFor (value=MoreSpecificChildBean)
public interface IMoreSpecificChildBeanProxy extends IChildBeanProxy
the Request context has a method that returns Request and i added the #ExtraTypes annotation here too:
#Service (value = CompareService.class, locator = SpringServiceLocator.class)
#ExtraTypes ({IChildBeanProxy.class, IMoreSpecificChildBeanProxy.class})
public interface ICompareRequestContext extends RequestContext {
Request <IRootBeanProxy> compare (Integer id1, Integer id2);
Question
Supposedly with those annotations, RF should be aware of the existence of polymorphic inherited classes, but all i get in the client is an IRootBeanProxy with a list of IChildBeanProxy elements. This list includes the MoreSpecificChildBean, but in the shape of a IChildBeanProxy, so that i cannot tell it from the others.
So i am wondering what i am doing wrong, if i am setting the ExtraTypes annotation at the wrong place or something.
Anyone?
Thx for all the help!!

I do the exact same thing for quite a few classes but it will always return me the base type which I can iterate through and test for instanceof if needed. You will probably have to cast the object to the subclass. If you do not add the #ExtraTypes you will know because on the server side you will get a message stating that MoreSpecificChildBean cannot be sent to the client.
I only annotate the service and not the proxy, I ran into some quirks with 2.4 adding #ExtraTypes to the proxy.
/**
* Base proxy that all other metric proxies extend. It is used mainly for it's
* inheritence with the RequestFactory. It's concrete implementation is
* {#link MetricNumber}.
*
* #author chinshaw
*/
#ProxyFor(value = Metric.class, locator = IMetricEntityLocator.class)
public interface MetricProxy extends DatastoreObjectProxy {
/**
* Name of this object in the ui. This will commonly be extended by
* subclasses.
*/
public String NAME = "Generic Metric";
/**
* This is a list of types of outputs that the ui can support. This is
* typically used for listing types of supported Metrics in the operation
* output screen.
*
* #author chinshaw
*/
public enum MetricOutputType {
MetricNumber, MetricString, MetricCollection, MetricStaticChart, MetricDynamicChart
}
/**
* See {#link MetricNumber#setName(String)}
*
* #param name
*/
public void setName(String name);
/**
* See {#link MetricNumber#setContext(String)}
*
* #return name of the metric.
*/
public String getName();
/**
* Get the list of violations attached to this metric.
*
* #return
*/
public List<ViolationProxy> getViolations();
}
#ProxyFor(value = MetricNumber.class, locator = IMetricEntityLocator.class)
public interface MetricNumberProxy extends MetricProxy {
public List<NumberRangeProxy> getRanges();
public void setRanges(List<NumberRangeProxy> ranges);
}
...
#ProxyFor(value = MetricDouble.class, locator = IMetricEntityLocator.class)
public interface MetricDoubleProxy extends MetricNumberProxy {
/* Properties when fetching the object for with clause */
public static String[] PROPERTIES = {"ranges"};
public Double getValue();
}
...
#ProxyFor(value = MetricPlot.class, locator = IMetricEntityLocator.class)
public interface MetricPlotProxy extends MetricProxy {
/**
* UI Name of the object.
*/
public String NAME = "Static Plot";
public String getPlotUrl();
}
This is a made up method from because I usually always return composite classes that may contain a list of metrics. That being said this will return me the base type of metrics, and then I can cast them.
#ExtraTypes({ MetricProxy.class, MetricNumberProxy.class, MetricDoubleProxy.class, MetricIntegerProxy.class})
#Service(value = AnalyticsOperationDao.class, locator = DaoServiceLocator.class)
public interface AnalyticsOperationRequest extends DaoRequest<AnalyticsOperationProxy> {
Request<List<<MetricProxy>> getSomeMetrics();
}
Not an exact method I use but will work for getting a proxy of type.
context.getSomeMetrics().with(MetricNumber.PROPERTIES).fire(new Receiver<List<MetricProxy>>() {
public void onSuccess(List<MetricProxy> metrics) {
for (MetricProxy metric : metrics) {
if (metric instanceof MetricDoubleProxy) {
logger.info("Got a class of double " + metric.getValue());
}
}
}
}
You will know if you are missing an #ExtraTypes annotation when you get the error stated above.
Hope that helps

Related

Typo3 Fluid extbase- How to execute external controller?

I have 2 different extension. I want to execute second controller (external) inside my first controller
Two different extension 1. Course , 2. Search
class CourseController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController {
/**
* courseRepository
*
* #var \TYPO3\Courses\Domain\Repository\CourseRepository
* #inject
*/
protected $courseRepository = NULL;
/**
* action list
*
* #return void
*/
public function listAction() {
/** I want to access Search extension Controller (f.e searchRepository->listAction() )**/
}
}
class SearchRepository extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController {
/**
* searchRepository
*
* #var \TYPO3\Courses\Domain\Repository\SearchRepository
* #inject
*/
protected $searchRepository = NULL;
/**
* action list
*
* #return void
*/
public function listAction() {
$searches = $this->searchRepository->findAll();
$this->view->assign('searches', $searches);
}
}
tl;dr:
Within a Controller, you usually forward() or redirect() to delegate to a different ControllerAction, e.g. delegate to SearchController::listAction() of 'myExtensionKey':
$this->forward('list', 'Search', 'myExtensionKey');
or
$this->redirect('list', 'Search', 'myExtensionKey');
Long version:
Quote from the MVC documentation of Flow which is quite similar to Extbase MVC:
Often, controllers need to defer execution to other controllers or
actions. For that to happen, TYPO3 Flow supports both, internal and
external redirects:
in an internal redirect which is triggered by forward(), the URI does
not change.
in an external redirect, the browser receives a HTTP
Location header, redirecting him to the new controller. Thus, the URI
changes.
The APIs are:
public void forward(string $actionName, string $controllerName=NULL, string $extensionName=NULL, array $arguments=NULL)
protected void redirect(string $actionName, string $controllerName=NULL, string $extensionName=NULL, array $arguments=NULL, integer $pageUid=NULL, int $delay=0, int $statusCode=303)
The programming API details can be found in the Extbase API

#Configurable not recognized in SpringBoot Application [duplicate]

I am having a strange problem with a custom jpa-entity listener I've created in a spring boot application. I'm trying to use Springs #Configurable mechanism to configure the EntityListener (as seen in Springs AuditingEntityListener) but Spring refuses to recognize my Listener as soon as it is used in the #EntityListeners-Annotation on a jpa entity. if it is not configured on a jpa entity, the Listener gets wired/configured by Spring as it should.
I've created an example project with a junit-test to demonstrate the problem:
https://github.com/chrisi/aopconfig/find/master
#SpringBootApplication
#EnableSpringConfigured
#EnableLoadTimeWeaving
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
The EntityListener:
/**
* This bean will NOT be instanciated by Spring but it should be configured by Spring
* because of the {#link Configurable}-Annotation.
* <p>
* The configuration only works if the <code>UnmanagedBean</code> is not used as an <code>EntityListener</code>
* via the {#link javax.persistence.EntityListeners}-Annotation.
*
* #see FooEntity
*/
#Configurable
public class UnmanagedBean {
#Autowired
private ManagedBean bean;
public int getValue() {
return bean.getValue();
}
}
The Bean I want to be injected in the EntityListener/UnmanagedBean:
/**
* This bean will be instanciated/managed by Spring and will be injected into the
* {#link UnmanagedBean} in the case the <code>UnmanagedBean</code> is not used as an JPA-EntityListener.
*/
#Component
#Data
public class ManagedBean {
private int value = 42;
}
The Entity where the Listener should be used:
/**
* This simple entity's only purpose is to demonstrate that as soon as
* it is annotated with <code>#EntityListeners({UnmanagedBean.class})</code>
* springs configurable mechanism will not longer work on the {#link UnmanagedBean}
* and therefore the <code>ConfigurableTest.testConfigureUnmanagedBean()</code> fails.
*/
#Entity
#EntityListeners({UnmanagedBean.class}) // uncomment to make the test fail
public class FooEntity {
#Id
private Long id;
private String bar;
}
And finally the test that shows that the wiring is not working as soon as the Listener is used:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
public class ConfigurableTest {
/**
* This test checks if the ManagedBean was injected into the UnmanagedBean
* by Spring after it was created with <code>new</code>
*/
#Test
public void testConfigureUnmanagedBean() {
UnmanagedBean edo = new UnmanagedBean();
int val = edo.getValue();
Assert.assertEquals(42, val);
}
}
The junit-test (the wiring of the EntityListener/ManagedBean) fails as soon as
the annotation #EntityListeners({UnmanagedBean.class}) in FooEntity is activated.
Is this a bug or did I miss something else?
In order to run the test you have to use -javaagent:spring-instrument-4.1.6.RELEASE.jar on the commandline an provide the jar file in the working directory.
This is the "condensed" version of a question I asked earlier:
#Configurable not recognized in SpringBoot Application

Injecting the Service Manager to Build a Doctrine Repository in ZF2

How do I inject the service manager into a Doctrine repository to allow me to retrieve the Doctrine Entity Manager?
I using the ZF2-Commons DoctrineORMModule and are trying to implement the repository example listed in the Doctrine Tutorial (bottom of tutorial in link below):
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/getting-started.html
However, I keep getting a message "Fatal error: Call to a member function get() on a non-object in C:\zendProject\zf2 ... ", which suggests that I do not have a working instance of the service locator.
My Doctrine repository looks like this:
namespace Calendar\Repository;
use Doctrine\ORM\EntityRepository,
Calendar\Entity\Appointment,
Calendar\Entity\Diary;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class ApptRepository extends EntityRepository implements ServiceLocatorAwareInterface
{
protected $services;
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->services = $serviceLocator;
}
public function getServiceLocator()
{
return $this->services;
}
public function getUserApptsByDate()
{
$dql = "SELECT a FROM Appointment a";
$em = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
$query = $em()->createQuery($dql);
return $query->getResult();
}
}
I then want to call this in my controller using the following pattern:
$diary = $em->getRepository('Calendar\Entity\Appointment')->getUserApptsByDate();
EDIT: The attached link suggests that I may need to convert the class to a service,
https://stackoverflow.com/a/13508799/1325365
However, if this is the best route, how would I then make my Doctrine Entity aware of the service. At the moment I include an annotation in the doc block pointing to the class.
#ORM\Entity (repositoryClass="Calendar\Repository\ApptRepository")
The way i approach things is this:
First i register a Service for each entity. This is done inside Module.php
public function getServiceConfig()
{
return array(
'factories' => array(
'my-service-entityname' => 'My\Factory\EntitynameServiceFactory',
)
);
}
Next thing would be to create the factory class src\My\Factory\EntitynameServiceFactory.php. This is the part where you inject the EntityManager into your Entity-Services (not into the entity itself, the entity doesn't need this dependency at all)
This class looks something like this:
<?php
namespace My\Factory;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\FactoryInterface;
use My\Service\EntitynameService;
class EntitynameServiceFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
$service = new EntitynameService();
$service->setEntityManager($serviceLocator->get('Doctrine\ORM\EntityManager'));
return $service;
}
}
Next thing in line is to create the src\My\Service\EntitynameService.php. And this is actually the part where you create all the getter functions and stuff. Personally i extend these Services from a global DoctrineEntityService i will first give you the code for the EntitynameService now. All this does is to actually get the correct repository!
<?php
namespace My\Service;
class EntitynameService extends DoctrineEntityService
{
public function getEntityRepository()
{
if (null === $this->entityRepository) {
$this->setEntityRepository($this->getEntityManager()->getRepository('My\Entity\Entityname'));
}
return $this->entityRepository;
}
}
This part until here should be quite easy to understand (i hope), but that's not all too interesting yet. The magic is happening at the global DoctrineEntityService. And this is the code for that!
<?php
namespace My\Service;
use Zend\EventManager\EventManagerAwareInterface;
use Zend\EventManager\EventManagerInterface;
use Zend\ServiceManager\ServiceManagerAwareInterface;
use Zend\ServiceManager\ServiceManager;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityRepository;
class DoctrineEntityService implements
ServiceManagerAwareInterface,
EventManagerAwareInterface
{
protected $serviceManager;
protected $eventManager;
protected $entityManager;
protected $entityRepository;
/**
* Returns all Entities
*
* #return EntityRepository
*/
public function findAll()
{
$this->getEventManager()->trigger(__FUNCTION__ . '.pre', $this, array('entities' => $entities));
$entities = $this->getEntityRepository()->findAll();
$this->getEventManager()->trigger(__FUNCTION__ . '.post', $this, array('entities' => $entities));
return $entities;
}
public function find($id) {
return $this->getEntityRepository()->find($id);
}
public function findByQuery(\Closure $query)
{
$queryBuilder = $this->getEntityRepository()->createQueryBuilder('entity');
$currentQuery = call_user_func($query, $queryBuilder);
// \Zend\Debug\Debug::dump($currentQuery->getQuery());
return $currentQuery->getQuery()->getResult();
}
/**
* Persists and Entity into the Repository
*
* #param Entity $entity
* #return Entity
*/
public function persist($entity)
{
$this->getEventManager()->trigger(__FUNCTION__ . '.pre', $this, array('entity'=>$entity));
$this->getEntityManager()->persist($entity);
$this->getEntityManager()->flush();
$this->getEventManager()->trigger(__FUNCTION__ . '.post', $this, array('entity'=>$entity));
return $entity;
}
/**
* #param \Doctrine\ORM\EntityRepository $entityRepository
* #return \Haushaltportal\Service\DoctrineEntityService
*/
public function setEntityRepository(EntityRepository $entityRepository)
{
$this->entityRepository = $entityRepository;
return $this;
}
/**
* #param EntityManager $entityManager
* #return \Haushaltportal\Service\DoctrineEntityService
*/
public function setEntityManager(EntityManager $entityManager)
{
$this->entityManager = $entityManager;
return $this;
}
/**
* #return EntityManager
*/
public function getEntityManager()
{
return $this->entityManager;
}
/**
* Inject an EventManager instance
*
* #param EventManagerInterface $eventManager
* #return \Haushaltportal\Service\DoctrineEntityService
*/
public function setEventManager(EventManagerInterface $eventManager)
{
$this->eventManager = $eventManager;
return $this;
}
/**
* Retrieve the event manager
* Lazy-loads an EventManager instance if none registered.
*
* #return EventManagerInterface
*/
public function getEventManager()
{
return $this->eventManager;
}
/**
* Set service manager
*
* #param ServiceManager $serviceManager
* #return \Haushaltportal\Service\DoctrineEntityService
*/
public function setServiceManager(ServiceManager $serviceManager)
{
$this->serviceManager = $serviceManager;
return $this;
}
/**
* Get service manager
*
* #return ServiceManager
*/
public function getServiceManager()
{
return $this->serviceManager;
}
}
So what does this do? This DoctrineEntityService pretty much is all what you globally need (to my current experience). It has the fincAll(), find($id) and the findByQuery($closure)
Your next question (hopefully) would only be "How to use this from my controller now?". It's as simple as to call your Service, that you have set up in the first step! Assume this code in your Controllers
public function someAction()
{
/** #var $entityService \my\Service\EntitynameService */
$entityService = $this->getServiceLocator()->get('my-service-entityname');
// A query that finds all stuff
$allEntities = $entityService->findAll();
// A query that finds an ID
$idEntity = $entityService->find(1);
// A query that finds entities based on a Query
$queryEntity = $entityService->findByQuery(function($queryBuilder){
/** #var $queryBuilder\Doctrine\DBAL\Query\QueryBuilder */
return $queryBuilder->orderBy('entity.somekey', 'ASC');
});
}
The function findByQuery() would expect an closure. The $queryBuilder (or however you want to name that variable, you can choose) will be an instance of \Doctrine\DBAL\Query\QueryBuilder. This will always be tied to ONE Repository though! Therefore entity.somekey the entity. will be whatever repository you are currently working with.
If you need access to the EntityManager you'd either only instantiate only the DoctrineEntityService or call the $entityService->getEntityManager() and continue from there.
I don't know if this approach is overly complex or something. When setting up a new Entity/EntityRepository, all you need to do is to add a new Factory and a new Service. Both of those are pretty much copy paste with two line change of code in each class.
I hope this has answered your question and given you some insight of how work with ZF2 can be organized.
As long as you extend the Doctrine\ORM\EntityRepository, you have immediate access to the entity manager by calling EntityRepository::getEntityManager() or the $_em attribute. The inheritence from the Doctrine\ORM\EntityRepository class allow you to do so.
Your method should now look like this:
public function getUserApptsByDate()
{
$dql = "SELECT a FROM Appointment a";
$em = $this->getEntityManager();// Or $em=$this->_em;
$query = $em()->createQuery($dql);
return $query->getResult();
}
I always keep in mind that access to my data should go from the web front (Zend MVC, Service Manager) to the persistence layer (Doctrine). My persistence (entities, repositories...) layer should not refer to the web front or neither know that it exists. If my system is doing the inverse at some level, then probably I'm doing something wrong.
Happy end of year

GWTP Handlers are Thread safe?

I am using gwt-platform for my application development.
I opened 2 browsers running the same application, i did 2 same operations with different data, but the now the browsers on the same view accessing the similar handler action
now the issue is the 2 browsers has updated with first received data from handler..
i am not understanding why it is not recognized the browsers which send the request... so this means its not Threadsafe...?
I seen #RequestedScope annotation in the Guice is it useful when i use on execute() of Handler
any suggestions?
Thanks in advance...
Maybe...
You have to made your Actions thread-safe. (attrs has final, e.g., inject in constructor), and perharps your logic has to be thread-safe too.
Btw, can you post a example of your action?
With 2 browsers you should have 2 different instances of your app running. In your onModuleLoad(), just put a System.out.println(this);. You should see different result which means you have different instances.
If you run an action from Browser 1, the action will be executed only in Browser 1. I don't know what your action is doing but if it updates data in the datastore (or DB) and since both instances share the persistence layer, you will see the new data in Browser 2 too.
It's very unlikely that the action triggered in Browser 1 is executed on both Browsers. It would mean that they share the same event bus.
public class InfoAction extends UnsecuredActionImpl<Response<ObjectTO>>
{
private List<OpenTO> request;
private String machineId;
private int actionType;
private UserBean userBean;
/**
* This is been in the case of double dated flight.
*/
private String orignalFpesLegId;
public List<OpenTO> getRequest() {
return request;
}
public void setRequest(List<OpenTO> request) {
this.request = request;
}
public String getMachineId() {
return machineId;
}
public void setMachineId(String machineId) {
this.machineId = machineId;
}
/**
* #return the actionType
*/
public int getActionType() {
return actionType;
}
/**
* #param actionType the actionType to set
*/
public void setActionType(int actionType) {
this.actionType = actionType;
}
/**
* #param userBean the userBean to set
*/
public void setUserBean(UserBean userBean) {
this.userBean = userBean;
}
/**
* #return the userBean
*/
public UserBean getUserBean() {
return userBean;
}
}
Please find my action class code

Cannot serialize an Enum to GWT

I am unable to serialize an Enum to GWT if it implements java.io.Serializable. It will GWT compile successfully, but at runtime, I get the dreaded:
Type 'com....security..AdminPrivilege' was not assignable to 'com.google.gwt.user.client.rpc.IsSerializable' and did not have a custom field serializer.For security purposes, this type will not be serialized.: instance = Login to Console
If I implement com.google.gwt.user.client.rpc.IsSerializable it compiles and runs fine. I am trying to avoid IsSerializable, since this Enum is persisted in our DB and is referenced in non-GWT servlets. I do not want to introduce a GWT dependancy, even for that single class.
I've read most of the discussions on this topic here. I have:
added a serialVersionUid (which should not be necessary)
added a no-arg constructor (but this is an Enum, so it must be private - I suspect this may be the problem)
added a callable RPC method that returns the Enum and takes a Set of the Enum as an input argument (trying to get this Enum into the whitelist) -
For all other Enums, I generated a GWT version which implements IsSerializable. But this new Enum is too complex to generate and I need the methods from the Enum in the GWT code.
Thanks for any help on this.
My Enum is below. Notice it has an embedded Enum:
public enum AdminPrivilege implements java.io.Serializable {
// Privileges
MANAGE_XX("Manage XX", PrivilegeCategory.XX),
IMPORT_LICENSE("Import a License", PrivilegeCategory.XX),
SUBMIT_BUG("Submit a Bug", PrivilegeCategory.XX),
TEST_AD("Test AD", PrivilegeCategory.XX),
// Administrator Privileges
LOGIN("Login to XX", PrivilegeCategory.ADMIN),
MANAGE_ADMIN("Manage Administrators", PrivilegeCategory.ADMIN),
MANAGE_ROLE("Manage Roles", PrivilegeCategory.ADMIN),
// Task Privileges
CANCEL_TASK("Cancel Tasks", PrivilegeCategory.TASK), ;
private static final long serialVersionUID = 1L;
/**
* Defines the privilege categories.
*
*/
public enum PrivilegeCategory implements java.io.Serializable {
XX("XX"),
ADMIN("Administrator"),
TASK("Task"), ;
private static final long serialVersionUID = 2L;
private String displayValue;
// This constructor is required for GWT serialization
private PrivilegeCategory() {
}
private PrivilegeCategory(String displayValue) {
this.displayValue = displayValue;
}
#Override
public String toString() {
return displayValue;
}
}
private String displayValue;
private AdminPrivilege parentPrivilege;
private PrivilegeCategory privilegeCategory;
// This constructor is required for GWT serialization
private AdminPrivilege() {
}
private AdminPrivilege(String displayValue, PrivilegeCategory category) {
this.displayValue = displayValue;
this.privilegeCategory = category;
}
private AdminPrivilege(String displayValue, PrivilegeCategory category, AdminPrivilege parent) {
this(displayValue, category);
this.parentPrivilege = parent;
}
/**
* Return the parent privilege for this privilege.
*
* #return
*/
public AdminPrivilege getParentPrivilege() {
return parentPrivilege;
}
/**
* Return the category for this privilege.
*
* #return
*/
public PrivilegeCategory getPrivilegeCategory() {
return privilegeCategory;
}
/**
* Return the set of categories.
*
* #return
*/
public static Set<PrivilegeCategory> getPrivilegeCategories() {
Set<PrivilegeCategory> category = new HashSet<PrivilegeCategory>();
for (PrivilegeCategory c : PrivilegeCategory.values()) {
category.add(c);
}
return category;
}
/**
* Return the set of privileges for a category.
*
* #return
*/
public static Set<AdminPrivilege> getPrivileges(PrivilegeCategory category) {
Set<AdminPrivilege> privileges = new HashSet<AdminPrivilege>();
for (AdminPrivilege p : AdminPrivilege.values()) {
if (category.equals(p.getPrivilegeCategory())) {
privileges.add(p);
}
}
return privileges;
}
/**
* Return the set of child privileges for a specific privilege
*
* #param parent
* #return
*/
public static Set<AdminPrivilege> getChildPrivileges(AdminPrivilege parent) {
Set<AdminPrivilege> children = new HashSet<AdminPrivilege>();
for (AdminPrivilege priv : values()) {
if (parent.equals(priv.getParentPrivilege())) {
children.add(priv);
}
}
return children;
}
/**
* Return the set of privileges that are parent privileges
*
* #return
*/
public static Set<AdminPrivilege> getParentPrivileges() {
Set<AdminPrivilege> parents = new HashSet<AdminPrivilege>();
for (AdminPrivilege priv : values()) {
if (priv.getParentPrivilege() == null) {
parents.add(priv);
}
}
return parents;
}
}
}
Have you specified a parameterized constructor in your enum? If you have, and it has parameters, you need to remember to add a no-parameters constructor as well, even if you don't use it, because GWT will need it. Adding a parameterized constructor and forgetting to add a parameterless one gets me every time, at least with non-enum classes.