I'm trying to compare two String values, which on the console are identical, but the returned boolean is always false.
I'm talking about the login() method. I am using PostgreSQL.
This is my Service file:
#Service
public class UserService {
private UserRepository userRepository;
#Autowired
public UserService(UserRepository userRepository) {
this.userRepository=userRepository;
}
public List<Useraccount> getUsers() {
List<Useraccount> userList = new ArrayList<>();
userRepository.findAll().forEach(userList::add);
return userList;
}
public boolean login(String username, String password) {
Useraccount user = userRepository.findByUsername(username).orElseThrow(()-> new IllegalStateException("User with Username "+username+" not found"));
System.out.println(user.getUsername()+user.getPassword()+"out");
System.out.println(username+password+"in");
return (user.getUsername()==username);
}
public String userOutput(String username) {
Useraccount user = userRepository.findByUsername(username).orElseThrow(()-> new IllegalStateException("User with Username "+username+" not found"));
return user.getUsername();
}
}
This is my Repository file:
#Repository
public interface UserRepository extends CrudRepository<Useraccount, Long>{
Optional<Useraccount> findByUsername(String username);
}
This is my Controller file:
#RestController
#RequestMapping("/api/v1/user")
#CrossOrigin
public class UserController {
private UserService userService;
#Autowired
public UserController(UserService userService) {
this.userService=userService;
}
#GetMapping
private List<Useraccount> getUsers(){
return userService.getUsers();
}
#GetMapping("/login")
public boolean login(#RequestParam(required = true) String username, #RequestParam(required =
true) String password) {
return userService.login(username, password);
}
#GetMapping(path="{username}")
public String userOutput(#PathVariable("username") String username) {
return userService.userOutput(username);
}
}
This is my Console output:
Hibernate:
select
useraccoun0_.id as id1_1_,
useraccoun0_.password as password2_1_,
useraccoun0_.username as username3_1_
from
useraccount useraccoun0_
where
useraccoun0_.username=?
DeonisosPasswordout
DeonisosPasswordin
As you can see the in and out is identical, but the boolean always returns false for some reason.
Please use equals method comparison on strings if you re trying to compare the content. In simple words, == checks if both objects point to the same memory location whereas .equals() evaluates to the comparison of values in the objects. So, your login method should return below for accurate results.
return (user.getUsername().equals(username);
I have a spring-boot application and I use DTO like that:
Service
#Service
public class UnitOfMeasureServiceImpl implements IUnitOfMeasureService {
private final IUnitsOfMeasureRepository unitOfMeasureRepository;
#Autowired
public UnitOfMeasureServiceImpl(IUnitsOfMeasureRepository unitOfMeasureRepository) {
this.unitOfMeasureRepository = unitOfMeasureRepository;
}
#Override
public UnitOfMeasureDTO getUnitOfMeasureById(UUID id) {
Optional<UnitOfMeasure> optionalUnitOfMeasure = unitOfMeasureRepository.findById(id);
if (!optionalUnitOfMeasure.isPresent()){
// throw new ComponentNotFoundException(id);
return null;
}
return UnitOfMeasureDTO.factory(optionalUnitOfMeasure.get());
}
dto:
#Data
#JsonInclude(JsonInclude.Include.NON_NULL)
public class UnitOfMeasureDTO {
private String id;
private String name;
private String description;
private String sourceInfoCompanyName;
private String originalId;
public static UnitOfMeasureDTO factory(UnitOfMeasure unitOfMeasure) {
UnitOfMeasureDTO dto = new UnitOfMeasureDTO();
dto.id = unitOfMeasure.getId().toString();
dto.name = unitOfMeasure.getName();
dto.description = unitOfMeasure.getDescription();
dto.sourceInfoCompanyName = unitOfMeasure.getSourceInfo().getSourceCompany().getName();
dto.originalId = unitOfMeasure.getOriginalId();
return dto;
}
}
controller:
#RestController
#RequestMapping(UnitOfMeasureController.BASE_URL)
public class UnitOfMeasureController {
public static final String BASE_URL = "/api/sust/v1/unitOfMeasures";
private final IUnitOfMeasureService unitOfMeasureService;
public UnitOfMeasureController(IUnitOfMeasureService unitOfMeasureService) {
this.unitOfMeasureService = unitOfMeasureService;
}
#GetMapping(path = "/{id}")
#ResponseStatus(HttpStatus.OK)
public UnitOfMeasureDTO getUnitOfMeasureDTO(#PathVariable("id") UUID id) {
UnitOfMeasureDTO unitOfMeasureDTO = unitOfMeasureService.getUnitOfMeasureById(id);
return unitOfMeasureDTO;
}
So in my service I have getUnitOfMeasureById(UUID id) that return a UnitOfMeasureDTO.
Now I need to call, from another service, getUnitOfMeasureById(UUID id) that return the domain entity UnitOfMeasure. I think it's correct to call a service method from another service (not a controller method!) and the separation between business logic is at the service layer. So is it correct to have 2 methods: getUnitOfMeasureDTOById and getUnitOfMeasureById in the service? (getUnitOfMeasureDTOById call getUnitOfMeasureById to avoid code duplication)
I need to use #Service from another Spring project. I will need a REST call to invoke it but how am I suppose to do it?
This is the service:
#Service
public class LocationsService implements ILocationsService {
private final Logger logger = LoggerFactory.getLogger("LocationsService");
private final ILocationRepository locationRepository;
private final IEvseRepository evseRepository;
private final IConnectorRepository connectorRepository;
#PersistenceContext
private EntityManager entityManager;
#Autowired
public LocationsService(ILocationRepository locationRepository, IEvseRepository evseRepository, IConnectorRepository connectorRepository, EntityManager entityManager) {
this.locationRepository = locationRepository;
this.evseRepository = evseRepository;
this.connectorRepository = connectorRepository;
this.entityManager = entityManager;
}
public Location getLocation(String countryCode, String partyId, String id) {
return locationRepository.findByCountryCodeAndPartyIdAndId(countryCode, partyId, id);
}
public Location deleteLocation(String countryCode, String partyId, String id) {
Location location = locationRepository.findByCountryCodeAndPartyIdAndId(countryCode, partyId, id);
if (location == null) {
logger.info("Location does not exist.");
return null;
}
locationRepository.deleteById(location.getLocId());
return location;
}
I need to call the service in this controller. The controller is in a different project:
#RestController
#RequestMapping(value = "/locations", produces = MediaType.APPLICATION_JSON_VALUE)
#Api(tags = "Locations management")
public class LocationController {
#Autowired
private LocationsService locationsService;
#RequestMapping(method = RequestMethod.GET , produces = MediaType.APPLICATION_JSON_VALUE)
#ApiOperation(value = "Get Locations", notes = "Get locations", nickname = "getLocations",
authorizations = #Authorization(value = "Bearer"))
public ResponseEntity<List<LocationDto>> getLocations() {
List<LocationDto> locations = new ArrayList<>();
return new ResponseEntity<>(locations, HttpStatus.OK);
}
}
I searched for solutions but found nothing helpful and will appreciate any help.
Thank you!
I'm trying to solve a problem: When user click on delete a record and instead of delete it, this record will change status to 'false'.
I suppose to create stored procedures in MySQL like "getAllUser", "changeStatus" but I'm confusing what I have to do.
This is structure of my project:
-configuration
JpaConfiguration
-controller
RestApiController
-model
User
-Repository
UserRepository
-Service
UserService
UserServiceImpl
Then I expect the index page only get records that have status is 'true'.
Procedure
CREATE DEFINER=`root`#`localhost` PROCEDURE `getAllUsers`()
BEGIN
SELECT * FROM APP_USER where status = 0;
END
RestApiController
#RestController
#RequestMapping("/api")
public class RestApiController {
#Autowired
UserService userService;
#RequestMapping(value = "/user/", method = RequestMethod.GET)
public List<User> getAllUsers(Boolean status){
Boolean statusWhere = org.apache.commons.lang3.BooleanUtils.isNotTrue(false);
List<User> users = userServiceImpl.getAllUsers(statusWhere);
if (users == null){
return new ArrayList<>();
} else {
return users;
}
}
// Change status
#RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)
public ResponseEntity<?>deleteUserById(#PathVariable("id") long id){
logger.info("Delete User with id {}", id);
User currentUser = userService.findById(id);
currentUser.setStatus(true);
return new ResponseEntity<User>(currentUser, HttpStatus.OK);
}
model/User
#Entity
#NamedStoredProcedureQueries({
#NamedStoredProcedureQuery(
name = "getAllUsers",
procedureName = "getAllUsers",
resultClasses = {User.class},
parameters = {
#StoredProcedureParameter(
mode = ParameterMode.IN,
name = "status",
type = Boolean.class)
}
)
})
service/UserServiceImpl
#Component
#Service("userService")
#Transactional
public class UserServiceImpl implements UserService {
#Autowired
private EntityManager entityManager;
#SuppressWarnings("unchecked")
public List<User> getAllUsers(Boolean status){
StoredProcedureQuery storedProcedureQuery = this.entityManager.createNamedStoredProcedureQuery("getAllUsers");
storedProcedureQuery.setParameter("status",status);
storedProcedureQuery.execute();
return storedProcedureQuery.getResultList();
}
public boolean isUserExist(User user) {
return findByName(user.getName()) != null;
}
}
I'm trying to test some services with Mockito but I have problems when the main class that I test and where I inject Mocks calls to super.
I run the project with spring and these are the steps I follow to get the error.
Here is where I create the test
public class UrlShortenerTests {
private MockMvc mockMvc;
#Mock
private ShortURLRepository shortURLRepository;
#Mock
private ClickRepository clickRespository;
#InjectMocks
private UrlShortenerControllerWithLogs urlShortenerWL;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.standaloneSetup(urlShortenerWL).build();
}
#Test
public void thatShortenerCreatesARedirectIfTheURLisOK() throws Exception {
mockMvc.perform(post("/link")
.param("url", "http://www.google.com"))
.andDo(print())
.andExpect(status().isCreated())
.andExpect(jsonPath("$.target", is("http://example.com/")));
}
}
Here is the class UrlShortenerControllerWithLogs with the method shortener, which is the one I want to test with the previous POST call
#RestController
public class UrlShortenerControllerWithLogs extends UrlShortenerController {
#Autowired
private ClickRepository clickRepository;
#Autowired
private ShortURLRepository SURLR;
public ResponseEntity<ShortURL> shortener(#RequestParam("url") String url,
#RequestParam(value = "sponsor", required = false) String sponsor,
#RequestParam(value = "brand", required = false) String brand,
HttpServletRequest request) {
ResponseEntity<ShortURL> su = super.shortener(url, sponsor, brand,
request);
return su;
}
And this is the super class
#RestController
public class UrlShortenerController {
#Autowired
protected ShortURLRepository shortURLRepository;
#Autowired
protected ClickRepository clickRepository;
#RequestMapping(value = "/link", method = RequestMethod.POST)
public ResponseEntity<ShortURL> shortener(#RequestParam("url") String url,
#RequestParam(value = "sponsor", required = false) String sponsor,
#RequestParam(value = "brand", required = false) String brand,
HttpServletRequest request) {
ShortURL su = createAndSaveIfValid(url, sponsor, brand, UUID
.randomUUID().toString(), extractIP(request));
if (su != null) {
HttpHeaders h = new HttpHeaders();
h.setLocation(su.getUri());
return new ResponseEntity<>(su, h, HttpStatus.CREATED);
} else {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
}
protected ShortURL createAndSaveIfValid(String url, String sponsor,
String brand, String owner, String ip) {
UrlValidator urlValidator = new UrlValidator(new String[] { "http",
"https" });
if (urlValidator.isValid(url)) {
String id = Hashing.murmur3_32()
.hashString(url, StandardCharsets.UTF_8).toString();
ShortURL su = new ShortURL(id, url,
linkTo(
methodOn(UrlShortenerController.class).redirectTo(
id, null)).toUri(), sponsor, new Date(
System.currentTimeMillis()), owner,
HttpStatus.TEMPORARY_REDIRECT.value(), true, ip, null);
return shortURLRepository.save(su);
} else {
return null;
}
}
So, when I call to shortURLRepository.save(su) in the second method (createAndSaveIfValid), it never enters in the method save, so it returns me null instead of the object I want.
The code of the implementation of ShortURLRepository and the method save is:
#Repository
public class ShortURLRepositoryImpl implements ShortURLRepository {
private static final Logger log = LoggerFactory
.getLogger(ShortURLRepositoryImpl.class);
#Override
public ShortURL save(ShortURL su) {
try {
jdbc.update("INSERT INTO shorturl VALUES (?,?,?,?,?,?,?,?,?)",
su.getHash(), su.getTarget(), su.getSponsor(),
su.getCreated(), su.getOwner(), su.getMode(), su.getSafe(),
su.getIP(), su.getCountry());
} catch (DuplicateKeyException e) {
log.debug("When insert for key " + su.getHash(), e);
return su;
} catch (Exception e) {
log.debug("When insert", e);
return null;
}
return su;
}
I think that the problem is that the object ShortURLRepository created in the test class is not initialized on the super class (UrlShortenerController) or something similar.
Is it possible?
Can anybody help me?
The full code is in: https://github.com/alberto-648702/UrlShortener2014
The class UrlShortenerTests is in:
bangladeshGreen/src/test/java/urlshortener2014/bangladeshgreen
The class UrlShortenerControllerWithLogs is in:
bangladeshGreen/src/main/java/urlshortener2014/bangladeshgreen/web
The class UrlShortenerController is in:
common/src/main/java/urlshortener2014/common/web
The class ShortURLRepositoryImpl is in:
common/src/main/java/urlshortener2014/common/repository
This is not an error. This is the expected behaviour. #Mock creates a mock. #InjectMocks creates an instance of the class and injects the mocks that are created with the #Mock. A mock is not a real object with known values and methods. It is an object that has the same interface as the declared type but you control its behaviour. By default the mocked object methods do nothing (e.g. return null). Therefore if ShortURLRepository is mocked and injected in UrlShortenerControllerWithLogs calling save in the injected ShortURLRepository does not call the real code as you expected, it does nothing. If you want to mock the behaviour of save, add the following code in your setup:
when(shortURLRepository.save(org.mockito.Matchers.any(ShortURL.class))).
then(new Answer<ShortURL>() {
#Override
public ShortURL answer(InvocationOnMock invocation) throws Throwable {
ShortURL su = (ShortURL) invocation.getArguments()[0];
// Do something with su if needed
return su;
}
});