diff --git a/java/roomBooking/src/main/java/com/uva/monolith/services/users/controllers/UserController.java b/java/roomBooking/src/main/java/com/uva/monolith/services/users/controllers/UserController.java
index 166922605ed07e3a9dcc87c6b38ea8af23ea7899..32b8c4d9fdfe17b26a913dd062fe19302e1bb90c 100644
--- a/java/roomBooking/src/main/java/com/uva/monolith/services/users/controllers/UserController.java
+++ b/java/roomBooking/src/main/java/com/uva/monolith/services/users/controllers/UserController.java
@@ -1,7 +1,5 @@
 package com.uva.monolith.services.users.controllers;
 
-import java.time.LocalDate;
-import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
@@ -19,15 +17,11 @@ import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.server.ResponseStatusException;
+import org.springframework.web.client.HttpClientErrorException;
 
-import com.uva.monolith.services.bookings.models.Booking;
-import com.uva.monolith.services.users.models.Client;
 import com.uva.monolith.services.users.models.User;
-import com.uva.monolith.services.users.models.UserRol;
 import com.uva.monolith.services.users.models.UserStatus;
-import com.uva.monolith.services.users.repositories.ClientRepository;
-import com.uva.monolith.services.users.repositories.UserRepository;
+import com.uva.monolith.services.users.services.UserService;
 
 @RestController
 @RequestMapping("users")
@@ -35,103 +29,82 @@ import com.uva.monolith.services.users.repositories.UserRepository;
 public class UserController {
 
   @Autowired
-  private UserRepository userRepository;
-
-  @Autowired
-  private ClientRepository clientRepository;
+  private UserService userService;
 
   @GetMapping
-  public List<User> getAllUsers() {
-    return userRepository.findAll();
+  public ResponseEntity<List<User>> getAllUsers() {
+    List<User> users = userService.getAllUsers();
+    return ResponseEntity.ok(users);
   }
 
   @GetMapping(params = { "email" })
   public ResponseEntity<?> getUserByEmail(@RequestParam String email) {
     try {
-      return new ResponseEntity<User>(userRepository.findByEmail(email).orElseThrow(), HttpStatus.ACCEPTED);
-    } catch (Exception e) {
-      return new ResponseEntity<>(HttpStatus.NOT_FOUND);
+      return ResponseEntity.ok(userService.getUserByEmail(email));
+    } catch (HttpClientErrorException e) {
+      if (e.getStatusCode() == HttpStatus.NOT_FOUND)
+        return new ResponseEntity<String>(HttpStatus.NOT_FOUND);
+      throw e;
     }
   }
 
   @PostMapping
-  public User addUser(@RequestBody User user) {
-    // user.setStatus(UserStatus.NO_BOOKINGS);
-    if (user.getRol() == null) // Rol por defecto
-      user.setRol(UserRol.CLIENT);
-    return userRepository.save(user);
+  public ResponseEntity<?> addUser(@RequestBody User user) {
+    userService.addUser(user);
+    return new ResponseEntity<>(HttpStatus.ACCEPTED);
   }
 
   @GetMapping("/{id}")
-  public User getUserById(@PathVariable int id) {
-    return userRepository.findById(id).orElseThrow();
+  public ResponseEntity<?> getUserById(@PathVariable int id) {
+    return ResponseEntity.ok(userService.getUserById(id));
   }
 
   @PutMapping("/{id}")
-  public User updateUserData(@PathVariable int id, @RequestBody Map<String, String> json) {
-    User target = userRepository.findById(id).orElseThrow();
-    if (!json.containsKey("name") || !json.containsKey("email")) {
-      // TODO cambiar manejo
-      throw new RuntimeException("Missing required fields");
+  public ResponseEntity<?> updateUserData(@PathVariable int id, @RequestBody Map<String, String> json) {
+    String name = json.get("name");
+    String email = json.get("email");
+    if (name == null || email == null) {
+      return new ResponseEntity<String>("Missing required fields", HttpStatus.BAD_REQUEST);
+    }
+    try {
+      User user = userService.updateUserData(id, name, email);
+      return new ResponseEntity<User>(user, HttpStatus.OK);
+    } catch (HttpClientErrorException e) {
+      if (e.getStatusCode() == HttpStatus.NOT_FOUND)
+        return new ResponseEntity<String>(HttpStatus.NOT_FOUND);
+      throw e;
     }
-    target.setName(json.get("name"));
-    target.setEmail(json.get("email"));
-    return userRepository.save(target);
   }
 
   @PatchMapping("/{id}")
-  public User updateUserState(@PathVariable int id, @RequestBody Map<String, String> json) {
-    Client target = clientRepository.findById(id).orElseThrow();
+  public ResponseEntity<?> updateUserState(@PathVariable int id, @RequestBody Map<String, String> json) {
+
     String strStatus = json.get("status");
     if (strStatus == null) {
-      // TODO cambiar manejo
-      throw new RuntimeException("Missing required fields");
+      return new ResponseEntity<String>("Missing required fields", HttpStatus.BAD_REQUEST);
     }
-    UserStatus userStatus = UserStatus.valueOf(strStatus);
-
-    boolean activeBookings = target.getBookings().stream()
-        .anyMatch(booking -> !booking.getEndDate().isBefore(LocalDate.now())); // reserva >= ahora
-    boolean inactiveBookings = target.getBookings().stream()
-        .anyMatch(booking -> booking.getStartDate().isBefore(LocalDate.now())); // reserva < ahora
-
-    switch (userStatus) {
-      // TODO Buscar como validar las (in)active bookings
-      case NO_BOOKINGS:
-        if (!target.getBookings().isEmpty())
-          throw new IllegalArgumentException("Invalid State: The user has at least one booking");
-        break;
-      case WITH_ACTIVE_BOOKINGS:
-        if (target.getBookings().isEmpty())
-          throw new IllegalArgumentException("Invalid State: The user don't has bookings");
-        if (!activeBookings)
-          throw new IllegalArgumentException("Invalid State: The user don't has active bookings");
-        break;
-      case WITH_INACTIVE_BOOKINGS:
-        if (target.getBookings().isEmpty())
-          throw new IllegalArgumentException("Invalid State: The user don't has bookings");
-        if (!inactiveBookings)
-          throw new IllegalArgumentException("Invalid State: The user don't has inactive bookings");
-        break;
-      default:
-        break;
+    try {
+      UserStatus userStatus = UserStatus.valueOf(strStatus);
+      return ResponseEntity.ok(userService.updateUserStatus(id, userStatus));
+    } catch (IllegalArgumentException e) {
+      return new ResponseEntity<String>("Unknown user state", HttpStatus.BAD_REQUEST);
+    } catch (HttpClientErrorException e) {
+      if (e.getStatusCode() == HttpStatus.NOT_FOUND)
+        return new ResponseEntity<String>(HttpStatus.NOT_FOUND);
+      throw e;
     }
-    target.setStatus(userStatus);
-    return userRepository.save(target);
+
   }
 
   @DeleteMapping("/{id}")
-  public User deleteUser(@PathVariable Integer id) {
-    User target;
-    if ((target = userRepository.findById(id).orElseThrow()) != null) {
-      userRepository.deleteById(id);
+  public ResponseEntity<?> deleteUser(@PathVariable Integer id) {
+    try {
+      return ResponseEntity.ok(userService.deleteUserById(id));
+    } catch (HttpClientErrorException e) {
+      if (e.getStatusCode() == HttpStatus.NOT_FOUND)
+        return new ResponseEntity<String>(HttpStatus.NOT_FOUND);
+      throw e;
     }
-    return target;
-  }
-
-  @GetMapping("/{id}/bookings")
-  public List<Booking> getUserBookingsById(@PathVariable int id) {
-    Client user = clientRepository.findById(id).orElseThrow();
-    return user.getBookings();
   }
 
 }
diff --git a/java/roomBooking/src/main/java/com/uva/monolith/services/users/services/UserService.java b/java/roomBooking/src/main/java/com/uva/monolith/services/users/services/UserService.java
new file mode 100644
index 0000000000000000000000000000000000000000..66c072eb6df93d66f93ee52d2177a3520dcbb810
--- /dev/null
+++ b/java/roomBooking/src/main/java/com/uva/monolith/services/users/services/UserService.java
@@ -0,0 +1,97 @@
+package com.uva.monolith.services.users.services;
+
+import java.time.LocalDate;
+import java.util.List;
+import java.util.Optional;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.HttpClientErrorException;
+
+import com.uva.monolith.services.users.models.User;
+import com.uva.monolith.services.users.models.UserRol;
+import com.uva.monolith.services.users.models.UserStatus;
+import com.uva.monolith.services.users.repositories.UserRepository;
+
+@Service
+public class UserService {
+
+  @Autowired
+  private UserRepository userRepository;
+
+  public List<User> getAllUsers() {
+    return userRepository.findAll();
+  }
+
+  private User assertUser(Optional<User> opUser) {
+    return opUser.orElseThrow(() -> new HttpClientErrorException(HttpStatus.NOT_FOUND));
+  }
+
+  public User getUserById(int id) {
+    return assertUser(userRepository.findById(id));
+  }
+
+  public User getUserByEmail(String email) {
+    return assertUser(userRepository.findByEmail(email));
+  }
+
+  public User addUser(User user) {
+    // TODO Introducir medidas de seguridad?
+    // Establecemos valores por defecto
+    user.setStatus(UserStatus.NO_BOOKINGS);
+    if (user.getRol() == null) // Rol por defecto
+      user.setRol(UserRol.CONSUMER);
+    // Guardamos
+    return userRepository.save(user);
+  }
+
+  public User updateUserData(int id, String name, String email) {
+    User user = getUserById(id);
+    user.setName(name);
+    user.setEmail(email);
+    return userRepository.save(user);
+  }
+
+  public User updateUserStatus(int id, UserStatus status) {
+
+    User user = getUserById(id);
+
+    boolean activeBookings = user.getBookings().stream()
+        .anyMatch(booking -> !booking.getEndDate().isBefore(LocalDate.now())); // reserva >= ahora
+    boolean inactiveBookings = user.getBookings().stream()
+        .anyMatch(booking -> booking.getStartDate().isBefore(LocalDate.now())); // reserva < ahora
+
+    switch (status) {
+      // TODO Buscar como validar las (in)active bookings
+      case NO_BOOKINGS:
+        if (!user.getBookings().isEmpty())
+          throw new IllegalArgumentException("Invalid State: The user has at least one booking");
+        break;
+      case WITH_ACTIVE_BOOKINGS:
+        if (user.getBookings().isEmpty())
+          throw new IllegalArgumentException("Invalid State: The user don't has bookings");
+        if (!activeBookings)
+          throw new IllegalArgumentException("Invalid State: The user don't has active bookings");
+        break;
+      case WITH_INACTIVE_BOOKINGS:
+        if (user.getBookings().isEmpty())
+          throw new IllegalArgumentException("Invalid State: The user don't has bookings");
+        if (!inactiveBookings)
+          throw new IllegalArgumentException("Invalid State: The user don't has inactive bookings");
+        break;
+      default:
+        break;
+    }
+    user.setStatus(status);
+    return userRepository.save(user);
+  }
+
+  public User deleteUserById(int id) {
+    User user = getUserById(id);
+    // TODO eliminar reservas de usuario ahora mismo no por el modo cascada pero a
+    // futuro sí, después de la disgregación en microservicios
+    userRepository.deleteById(id);
+    return user;
+  }
+}