Search code examples
javascriptangularjsspringmodel-view-controllerhateoas

AngularJS Spring sort field names


I'm developing an application using AngularJS for the front-end part and Spring for the back-end.

I have mainly two entity classes :

@Entity
public class Project implements Serializable {

private static final long serialVersionUID = 1L;


/**
 * idProject
 */
@Id
@GeneratedValue(strategy=AUTO, generator="PROJECT_SEQ")    
private Integer idProject;


/**
 * name
 */
@Column(name="PROJECT_NAME")
private String name;


/**
 * date
 */
@Column(name="PROJECT_DATE")
private Date date;


/**
 * technology
 */
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name="ID_TECHNOLOGY", nullable=true)
@ForeignKey(name = "FK_PROJECT_TECHNOLOGY")
private Technology technology;

and

@Entity
public class Technology implements Serializable {

 /**
 * idTechnology
 */
@Id
@Column(name="ID_TECHNOLOGY", length=2)
private Integer idTechnology;


/**
 * ID = 0 ==> "TechA"
 * ID = 1 ==> "TechB";
 * ID = 2 ==> "TechC";
 * ID = 3 ==> "TechD";
 * ID = 4 ==> "TechE"
 */
@Column(name="TECHNOLOGY", length=30)
private String technology;

What I'm trying to do is, providing projects list for the AngularJS application.

For that I have created a controller :

@Autowired
private ProjectAssembler projectAssembler;

@RequestMapping(method = RequestMethod.GET, produces = "application/json")
@ResponseBody
public PagedResources<ProjectResource> findAll(
    @PageableDefault Pageable page,
    PagedResourcesAssembler<Project> assembler) {

    //Request
    Page<Project> projectPage = projectRepo.findAll(page);

    PagedResources<ProjectResource> resources = assembler.toResource(projectPage, projectAssembler);
    return resources;
}

As you can see, I'm using Hateoas for creating the JSON resources list and providing links for browsing. In addition to this I'm using dozer to map Project class to ProjectResource class in the ProjectAssembler.

public class ProjectResource extends ResourceSupport {

private Integer idProject;
private String projectName;
private Date projectDate;
private String technologyName;

And The Assembler

@Component
public class ProjectResourceAssembler extends ResourceAssemblerSupport<Project, ProjectResource> {

@Autowired
private Mapper dozerBeanMapper;

public ProjectResourceAssembler() {
    super(ProjectController.class, ProjectResource.class);
}

@Override
public ProjectResource toResource(Project entity) {
    ProjectResource resource = createResourceWithId(entity.getIdProject(), entity);
    return resource;
}

@Override
protected ProjectResource instantiateResource(Project entity) {
    return dozerBeanMapper.map(entity, ProjectResource.class);
}

}

The goal is that I wanted to have different fields names in the front-end AngularJS application that in the back-end. For example the ProjectResources fields are the columns of projects table list in the front-end.

My problem is when i want to use sort in the angularjs app, I use front end fields name, same when i want to filter, so when the controller receives the Page attribute it does't know the fields of the sort.

My question is : do you have any advises to help me use sort ?


Solution

  • To be truly HATEOAS compliant, the service (spring) needs to provide to the client all the hypermedia controls (links) to perform sorting. The client should never sort by some data field...it should only sort by what sort options are provided to the client by the server. This sorting may itself be all the data fields of the result, but that's only by chance of your use case.

    This way the service can embed the sorting rules in each link. The sorting rule can contain the backend column name. The sort url itself is opaque to the client.

    I realize this doesn't give you a direct answer, but you should be able to use the link builder to create sorting links as appropriate and return those.