Studio Developer Manual / Version 2010
Table Of Contents
Let's start with implementing a so called EntityController class. An instance of EntityController is
created for every remote bean that is created in the Studio via the call
beanFactory.getRemoteBean(...)
EntityControllers
are used when you have multiple elements of the same type in Studio, Content instances
in Studio, for example, are created through EntityControllers. The same applies for messages
of the notification API or CMS users and user groups.
In this example, you will create entities that represent notes created by users. The user should be able to create, update and delete notes.
The note model would look like this:
public class Note {
private String description;
private String owner;
private String noteId;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getNoteId() {
return noteId;
}
public void setNoteId(String noteId) {
this.noteId = noteId;
}
}
Example 7.94. Note model
You also need a representation class for this model (the reason for this will be explained later).
public class NoteRepresentation {
private String description;
private String owner;
private String noteId;
NoteRepresentation(Note note) {
this.description = note.getDescription();
this.owner = note.getOwner();
this.noteId = note.getNoteId();
}
public String getDescription() {
return description;
}
public String getOwner() {
return owner;
}
public String getNoteId() {
return noteId;
}
}
Example 7.95. Representation class for note model
You also have a service which handles the notes:
@DefaultAnnotation(NonNull.class)
public class NotesService {
private final List<Note> list;
public NotesService() {
list = new ArrayList<>();
Note dummy1 = new Note();
dummy1.setOwner("me");
dummy1.setNoteId("1");
dummy1.setDescription("I have to write a real storage for this!");
Note dummy2 = new Note();
dummy2.setOwner("me");
dummy2.setNoteId("2");
dummy2.setDescription("And a lot of other stuff too!");
list.add(dummy1);
list.add(dummy2);
}
@Nullable
public Note getNote(String id) {
return list.stream().filter(note -> id.equals(note.getNoteId())).findFirst().orElse(null);
}
public boolean deleteNote(String id) {
Note noteToDelete = getNote(id);
if (noteToDelete == null) {
return false;
}
list.retainAll(
list.stream().filter(note -> note != noteToDelete).collect(Collectors.toList())
);
return true;
}
@Nullable
public Note updateNote(String id, String description) {
Note note = getNote(id);
if (note == null) {
return null;
}
note.setDescription(description);
return note;
}
public List<Note> getNotes() {
return Collections.unmodifiableList(list);
}
public void setNotes(List<Note> notes) {
list.clear();
list.addAll(notes);
}
}
Example 7.96. Service for note handling
So you have a note with a description, an owner and an ID and a service you can query for notes. You now have to
create the EntityController class that wraps the REST operations around it:
@RestController
@RequestMapping(value = "notes/note/{" + NoteEntityController.PATH_PARAM_ID + "}", produces = MediaType.APPLICATION_JSON_VALUE)
public class NoteEntityController implements EntityController<Note> {
public static final String PATH_PARAM_ID = "id";
private final NotesService notesService;
public NoteEntityController(NotesService notesService) {
this.notesService = notesService;
}
@Override
public Note getEntity(@NonNull Map<String, String> params) {
return notesService.getNote(params.get(PATH_PARAM_ID));
}
@NonNull
@Override
public Map<String, String> getPathVariables(@NonNull Note entity) {
HashMap<String, String> map = new HashMap<>();
map.put(PATH_PARAM_ID, entity.getNoteId());
return map;
}
@GetMapping
public ResponseEntity<NoteRepresentation> getRepresentation(@PathVariable Map<String, String> params) {
Note note = getEntity(params);
if (note == null) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(new NoteRepresentation(note));
}
@DeleteMapping
public boolean delete(@PathVariable Map<String, String> params) {
Note note = getEntity(params);
if (note == null) {
return false;
}
return notesService.deleteNote(note.getNoteId());
}
@PutMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<NoteRepresentation> setProperties(@PathVariable final Map<String, String> params,
@RequestBody final Map<String, Object> json) {
String description = (String) json.get("description");
Note note = getEntity(params);
if (note == null) {
return ResponseEntity.notFound().build();
}
Note updatedNote = notesService.updateNote(note.getNoteId(), description);
if (updatedNote == null) {
return ResponseEntity.badRequest().build();
}
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(new NoteRepresentation(updatedNote));
}
}
Example 7.97. Entity Controller class for TEST operations
Have a look on the class NoteEntityController in detail:
@RestController
@RequestMapping(value = "notes/note/{" + NoteEntityController.PATH_PARAM_ID + "}", produces = MediaType.APPLICATION_JSON_VALUE)Example 7.98. Annotation for bean creation
The first two annotations are used to tell Spring what kind of bean you are creating. The first annotation states
that the class represents a REST controller. The @RequestMapping annotation provides the REST configuration.
The produces value defines that all requests expecting the JSON format will be accepted and the
value property tells Spring under which URL the entity can be invoked. Note that the URL can have
multiple path parameters. This example shows the most simple form with only one Id parameter.
The class has one REST GET method:
@GetMapping
public ResponseEntity<NoteRepresentation> getRepresentation(@PathVariable Map<String, String> params) {
Note note = getEntity(params);
if (note == null) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(new NoteRepresentation(note));
}Example 7.99. REST GET method of NoteEntityController
So when a GET is executed on this controller, the note NoteRepresentation is returned and serialized to
JSON. If the return format should differ from the originating model, you can freely customize the representation
class. Because of the automatic REST linking, it is important that you don't return the the same class here that
has been defined as type of the EntityController! You can put models of other EntityControllers inside your
representation as well. These entities will be converted to references during serialization. By this, different
EntityControllers can be linked to each other. So you always have to create a representation class for the model
that is bound for the EntityController. You just have to make sure that this representation contains
the fields that should be supported by the RemoteBean you will implement.
Note
Note that in this example, it is not covered how and where these notes are stored. The methods in NotesService
have to be implemented properly to support a real data access layer.
Next, add support for deletion by adding the following method:
@DeleteMapping
public boolean delete(@PathVariable Map<String, String> params) {
Note note = getEntity(params);
if (note == null) {
return false;
}
return notesService.deleteNote(note.getNoteId());
}Example 7.100. Deletion of note in NoteEntityController
The method is pretty simple: if a DELETE request is executed in the controller, the corresponding helper is invoked and the note is deleted.
The same applies for updates:
@PutMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<NoteRepresentation> setProperties(@PathVariable final Map<String, String> params,
@RequestBody final Map<String, Object> json) {
String description = (String) json.get("description");
Note note = getEntity(params);
if (note == null) {
return ResponseEntity.notFound().build();
}
Note updatedNote = notesService.updateNote(note.getNoteId(), description);
if (updatedNote == null) {
return ResponseEntity.badRequest().build();
}
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(new NoteRepresentation(updatedNote));
}Example 7.101. Update of note in NoteEntityController
You have finished the Java part now. Finally, you have to declare the entity as bean in the Spring configuration:
@Bean
public NotesService notesService() {
return new NotesService();
}
@Bean
public NoteEntityController noteEntityController(NotesService notesService) {
return new NoteEntityController(notesService);
}Example 7.102. Declare NoteEntityController as bean
You can rebuild the module and restart Studio now. The next steps can be implemented using the incremental Studio build that doesn't require a Studio restart.


