Message Boards

Liferay 7.1 ServiceWrapper Example

Mike Perico, modified 5 Years ago.

Liferay 7.1 ServiceWrapper Example

Junior Member Posts: 25 Join Date: 8/23/12 Recent Posts
I was reading the example found at: https://dev.liferay.com/develop/tutorials/-/knowledge_base/7-1/customizing-liferay-services-service-wrappers
Right in the first paragraph it explains that you can use servicewrappers if you have added a new field to User. Unfortunately it does not go into detail on how to add a new field to User. I know we can add expando fields, but I rather not use them.

I would like to create my own table for persisting my new data. Is this possible?

I think it was possible in 6.0 to create a hook on model entities, but it doesn't seem possible to do that now. If I wanted to add about 8 fields to User how would I go about doing this? Is there an example?
thumbnail
Olaf Kock, modified 5 Years ago.

RE: Liferay 7.1 ServiceWrapper Example

Liferay Legend Posts: 6403 Join Date: 9/23/08 Recent Posts
Mike Perico

I was reading the example found at: https://dev.liferay.com/develop/tutorials/-/knowledge_base/7-1/customizing-liferay-services-service-wrappers
Right in the first paragraph it explains that you can use servicewrappers if you have added a new field to User. Unfortunately it does not go into detail on how to add a new field to User. I know we can add expando fields, but I rather not use them.

I would like to create my own table for persisting my new data. Is this possible?

I think it was possible in 6.0 to create a hook on model entities, but it doesn't seem possible to do that now. If I wanted to add about 8 fields to User how would I go about doing this? Is there an example?


The basic rule is: You can't change an implementation's interface.

The sentence that you're referring to is


Perhaps you’ve added a new field to Liferay’s User object and you want its value to be saved whenever the addUser or updateUser methods of Liferay’s API are called.
You can add fields to any of Liferay's entity by using "Expando" (their API name) or Custom Fields (their UI name). But changing the interface would not work, as it would invalidate all other plugins (e.g. servicewrappers) that are not aware of the new methods. This applies to services as well as to entities.
Mike Perico, modified 5 Years ago.

RE: Liferay 7.1 ServiceWrapper Example

Junior Member Posts: 25 Join Date: 8/23/12 Recent Posts
Olaf,

Is it possible (recommended) to create an osgi module that will hook UserImpl in someway? I don't want to change the User interface, but can I add methods to UserImpl that can link together a new model entity with the existing User entity?
thumbnail
Olaf Kock, modified 5 Years ago.

RE: Liferay 7.1 ServiceWrapper Example

Liferay Legend Posts: 6403 Join Date: 9/23/08 Recent Posts
Mike PericoOlaf,

Is it possible (recommended) to create an osgi module that will hook UserImpl in someway? I don't want to change the User interface, but can I add methods to UserImpl that can link together a new model entity with the existing User entity?
You also can't really change UserImpl, but you can create a custom class (or service), e.g. MyUser

Example: Create a standard Servicebuilder module. And if you don't need persistence for this entity, leave the entity fields in service.xml empty. You'll end up with classes that you can implement on your own, especially MyUserLocalService and its implementation. It's fine to let this one work on the standard User interface.
Mike Perico, modified 5 Years ago.

RE: Liferay 7.1 ServiceWrapper Example

Junior Member Posts: 25 Join Date: 8/23/12 Recent Posts
Olaf,

 Would it be possible to create a serviceBuilder module for say, Employee, that would contain my custom fields. Inside the module create a ModelWrapper (let's name it UserModelWrapper) for User that would add employee.

@Component(
    immediate = true,
    property = {
    },
    service = ModelWrapper.class
)
public class UserModelWrapper extends UserWrapper {

    /**
     *
     */
    private static final long serialVersionUID = 1L;

    @Reference
    EmployeeLocalService employeeLocalService;

    @Activate
    void activate() throws Exception {
        System.out.println("Activating " + this.getClass().getSimpleName());
    }

    public UserModelWrapper() {
            super(null);
    }
    
    private Employee employee;

    public Employee getEmployee() {
            return employee;
    }

    public void setEmployee(Employee _employee) {
            this.employee = _employee;
    }

}

Then would need to create a wrapper for UserLocalService to update all the CRUD methods to add my new Employee object to the User? If so, would I have to override the current methods or can I create new method signaures, as example.

    public com.liferay.portal.kernel.model.User addUser(User user) {

        employeeLocalService.addEmployee(user.getEmployee());
        return userLocalService.addUser(user);
    }

or would I need to do this:

    public UserModelWrapper addUser(UserModelWrapper user) {
        employeeLocalService.addEmployee(user.getEmployee());
        try {
            getWrappedService().addUser(getWrappedService().getUser(user.getUserId()));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return user;
    }
thumbnail
Olaf Kock, modified 5 Years ago.

RE: Liferay 7.1 ServiceWrapper Example

Liferay Legend Posts: 6403 Join Date: 9/23/08 Recent Posts
Mike Perico
(just quoting a tiny bit)
    public com.liferay.portal.kernel.model.User addUser(User user) {

        employeeLocalService.addEmployee(user.getEmployee());
        return userLocalService.addUser(user);
    }
Here it ends: You won't be able to add getEmployee() to the user interface. Period.
No other component in Liferay, that deals with User objects, will know what this is - it effectively would change the interface. And even if your wrapped UserLocalService returns objects that are ExtendedUsers, those objects would be passed out under the interface User, which doesn't have these extended methods.

What you can do is to define a new entity Employee, then implement EmployeeLocalService.getEmployee(User user) - or by userId. And you can have Employee.getUser(). But not the other way around. This way, however, all your custom code that knows about Employees and Users can still get all it needs.

And a wrapped UserLocalService can make sure that there is an Employee whenever a new User is added to the system. Or your own EmployeeLocalService can make sure that there's an employee whenever it's being asked for an object for an existing userId.
Mike Perico, modified 5 Years ago.

RE: Liferay 7.1 ServiceWrapper Example

Junior Member Posts: 25 Join Date: 8/23/12 Recent Posts
Olaf,

 Thank You.