How to make #JsonView annotated Rest apis serializes all fields - json

I have a rest api like "/users/{userId}"
This api returns User data but filters out password by #JsonView(ResourceView.Public.class) annotation.
But I want to get password when the unit test runs.
Is there a way to igore #JsonView annotation when test is running.
Or any other options for me?
public class ResourceView {
public interface Public {}
public interface Friends extends Public {}
public interface Family extends Friends {}
}
public class User {
#JsonView(ResourceView.Public.class)
private String name;
#JsonView(ResourceView.Family.class)
private String password;
}
#RestController
public class UserController {
#Autowired
private UserService userService;
#JsonView(ResourceView.Public.class)
#GetMapping(value = "/users/{userId}")
public User getUser(#PathVariable("userId") String userId) {
return userService.getUser(userId);
}
}
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.RANDOM_PORT)
#ActiveProfiles(profiles = "test")
public class UserServiceTest {
#Autowired
protected TestRestTemplate restTemplate;
#Value("${local.server.port}")
private int port;
protected String apiEndpoint;
#Before
protected void setUp() {
initRequestContext();
apiEndpoint = "http://localhost:" + port;
}
protected ResponseEntity<User> requestGetUser(String userId) {
ResponseEntity<User> res = restTemplate.exchange(
apiEndpoint + "/users/" + userId,
HttpMethod.GET,
new HttpEntity<>("parameters", createDefaultHttpHeaders()),
new ParameterizedTypeReference<User>() {});
return res;
}
#Test
public void testGetUser() throws Exception {
ResponseEntity<User> apiRes = requestGetUsers(request);
assertThat(apiRes.getStatusCode(), is(HttpStatus.OK));
User user = apiRes.getBody();
assertThat(user.getName(), is(notNullValue()));
assertThat(user.getPassword(), is(notNullValue()));
}
}
#Configuration
public class MyConfig {
#Bean
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper().configure(MapperFeature.DEFAULT_VIEW_INCLUSION, true);
return objectMapper;
}
}

Related

can't see the contents of DB in HTML

I connected my bat to the database.
I mapped it to view the contents in HTML,
but typing url(/index) in the address bar, I can only see the contents of the table.
What is the problem?
public class Controller {
#Autowired
noticeService ns;
#RequestMapping(value="/index", method = RequestMethod.GET)
public ModelAndView index (HttpServletRequest request) {
ModelAndView mav = new ModelAndView();
List<noticeModel>noticeList = ns.getNotice();
mav.addObject("noticeList", noticeList);
mav.setViewName("index"); // HTML ADDRESS
return mav;
}
}
#Builder #Data
public class noticeModel {
private int notice_id;
private String notice_tilte;
private String notice_name;
private Date notice_created_date;
private Date notice_revised_date;
private String notice_text;
private String notice_pw;
}
#Service
public class noticeService {
#Autowired
public noticeMapper mapper;
public List<noticeModel> getNotice() {
return mapper.getNotice();
}
}
#Repository
#Mapper
public interface noticeMapper {
List<noticeModel> getNotice();
}

Unable to get rid of 'Exception while fetching data(/{apiName})' in graphql-spqr-spring-boot-starter

I’m using ‘graphql-spqr-spring-boot-starter’ library version 0.0.4 of ‘io.leangen.graphql’. I'm able to customize errors. See the below code and screenshot for reference:
Models:
#Getter
#Setter
#ToString
#Entity
#Accessors
public class Student {
#Id
#GraphQLQuery(name = "id", description = "A Student's ID")
private Long id;
#GraphQLQuery(name = "name", description = "A student's name")
private String name;
private String addr;
}
Service class:
#Service
#GraphQLApi
public class StudentService{
private final StudentRepository studentRepository;
private final AddressRepository addressRepository;
public StudentService(StudentRepository studentRepository, AddressRepository addressRepository) {
this.addressRepository = addressRepository;
this.studentRepository = studentRepository;
}
#GraphQLQuery(name = "allStudents")
public List<Student> getAllStudents() {
return studentRepository.findAll();
}
#GraphQLQuery(name = "student")
public Optional<Student> getStudentById(#GraphQLArgument(name = "id") Long id) {
if(studentRepository.findById(id) != null)
return studentRepository.findById(id);
throw new StudentNotFoundException("We were unable to find a student with the provided id", "id");
}
#GraphQLMutation(name = "saveStudent")
public Student saveStudent(#GraphQLArgument(name = "student") Student student) {
if(student.getId() == null)
throw new NoIdException("Please provide an Id to create a Student entry.");
return studentRepository.save(student);
}
}
Customized Exception class:
import java.util.List;
import graphql.ErrorType;
import graphql.GraphQLError;
import graphql.language.SourceLocation;
public class NoIdException extends RuntimeException implements GraphQLError {
private String noIdMsg;
public NoIdException(String noIdMsg) {
this.noIdMsg = noIdMsg;
}
#Override
public List<SourceLocation> getLocations() {
// TODO Auto-generated method stub
return null;
}
#Override
public ErrorType getErrorType() {
// TODO Auto-generated method stub
return ErrorType.ValidationError;
}
#Override
public String getMessage() {
// TODO Auto-generated method stub
return noIdMsg;
}
}
However, I’m not sure how to get rid of Exception while fetching data (/saveStudent) as seen on the above screenshot for the message field. I know we can have GraphQLExceptionHandler class which implements GraphQLErrorHandler (graphql-java-kickstart). But what is the option for sqpr-spring-boot-starter?
import graphql.*;
import graphql.kickstart.execution.error.*;
import org.springframework.stereotype.*;
import java.util.*;
import java.util.stream.*;
#Component
public class GraphQLExceptionHandler implements GraphQLErrorHandler {
#Override
public List<GraphQLError> processErrors(List<GraphQLError> list) {
return list.stream().map(this::getNested).collect(Collectors.toList());
}
private GraphQLError getNested(GraphQLError error) {
if (error instanceof ExceptionWhileDataFetching) {
ExceptionWhileDataFetching exceptionError = (ExceptionWhileDataFetching) error;
if (exceptionError.getException() instanceof GraphQLError) {
return (GraphQLError) exceptionError.getException();
}
}
return error;
}
}
Could someone please help me how can I remove this statement and send just the specific message?
You can create a Bean and override DataFetcherExceptionHandler. To override it, you have to override the execution strategy too:
#Bean
public GraphQL graphQL(GraphQLSchema schema) {
return GraphQL.newGraphQL(schema)
.queryExecutionStrategy(new AsyncExecutionStrategy(new CustomDataFetcherExceptionHandler()))
.mutationExecutionStrategy(new AsyncSerialExecutionStrategy(new CustomDataFetcherExceptionHandler()))
.build();
}
private static class CustomDataFetcherExceptionHandler implements DataFetcherExceptionHandler {
#Override
public DataFetcherExceptionHandlerResult onException(DataFetcherExceptionHandlerParameters handlerParameters) {
Throwable exception = handlerParameters.getException();
SourceLocation sourceLocation = handlerParameters.getSourceLocation();
CustomExceptionWhileDataFetching error = new CustomExceptionWhileDataFetching(exception, sourceLocation);
return DataFetcherExceptionHandlerResult.newResult().error(error).build();
}
}
private static class CustomExceptionWhileDataFetching implements GraphQLError {
private final String message;
private final List<SourceLocation> locations;
public CustomExceptionWhileDataFetching(Throwable exception, SourceLocation sourceLocation) {
this.locations = Collections.singletonList(sourceLocation);
this.message = exception.getMessage();
}
#Override
public String getMessage() {
return this.message;
}
#Override
public List<SourceLocation> getLocations() {
return this.locations;
}
#Override
public ErrorClassification getErrorType() {
return ErrorType.DataFetchingException;
}
}

Caused by: org.springframework.dao.IncorrectResultSizeDataAccessException: query did not return a unique result: 3

I am new in spring security and i m building a application AuthSystems using spring-security and Msql
am using extera query method in JpaRepository and that methods are not return result, and show IncorrectResultSizeDataAccessException.
here is my code
UserRepository
package com.ganesh.repository;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import com.ganesh.model.User;
public interface UserRepository extends JpaRepository<User, Integer> {
User findByUsername(String username);
}
CustomUserDetailsService
#Service
public class CustomUserDetailsService implements UserDetailsService {
#Autowired
private UserRepository userRepo;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepo.findByUsername(username);
CustomeUserDetail userdetails = null;
if(user != null) {
userdetails = new CustomeUserDetail();
userdetails.setUser(user);
}else {
throw new UsernameNotFoundException("User not fond this username"+ username);
}
return userdetails;
}
}
CustomeUserDetail
#Getter
#Setter
public class CustomeUserDetail implements UserDetails {
/**
*
*/
private static final long serialVersionUID = -8354447536649796292L;
#Autowired
private User user;
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return user.getRoles().stream().map(role -> new SimpleGrantedAuthority("ROLE_"+ role)).collect(Collectors.toList());
}
#Override
public String getPassword() {
return user.getPassword();
}
#Override
public String getUsername() {
return user.getUsername();
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
}
#properties
spring.datasource.url=jdbc:mysql://${MYSQL_HOST:localhost}:3306/spring_auth
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.propertirs.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
hibernate.format_sql=true
Please help me...
It seems like there are multiple Users in your DB-Table with the same username. So User findByUsername(String username); returns more than one Result.
You could do one of the following things:
Make the username-Column in your DB unique.
Change your repository method to List<User> findByUsername(String username); to get all Users with that
username.
Change your repository method to User findFirstByUsername(String username); to get just one (random) User.

Spring Boot: How to retrieve the username by user_id?

I have already connected my springboot to MySQL database. I want to display the username when user_id is specified in the HTTP request. e.g. http://8080/user/1 must display the name of the user with user_id 1.
The table contains attributes as:
| Integer user_id; | String username; | String fathername; | String mothername;
I have already tried this code in by Controller class but i does not seem to be working
#RequestMapping("/{userid}")
#ResponseBody
public String getById(Integer userid) {
String name="";
try {
Optional<Persondetails> persondetails=persondetailsRepository.findById(personid);
name = String.valueOf(userdetails.getName());
}
catch (Exception ex) {
return "Name not found";
}
return "The Name of the user is : " + name;
}
my repository code:
import java.util.List;
import java.util.Optional;
public interface UserdetailsRepository extends JpaRepository<Userdetails, Integer> {
public Optional<Userdetails> findById(Integer userid);
}
It says getName() is undefined for the type Optional
But i have defined it in Userdetails class
public class Userdetails {
#Id
#GeneratedValue
#Column(name="user_id")
private Integer userid;
#Column(name="name")
private String name;
#Column (name="fathers_name")
private String fathersname;
#Column(name="mothers_name")
private String mothersname;
public Userdetails() {
}
public Integer getUserid() {
return userid;
}
public void setUserid(Integer userid) {
this.userid = userid;
}
public String getName() {
return name;
}
public void setname(String name) {
this.name = name;
}
public String getFathersname() {
return fathersname;
}
public void setFathersname(String fathersname) {
this.fathersname = fathersname;
}
public void setMothersname(String mothersname) {
this.mothersname = mothersname;
}
public String getMothersname() {
return mothersname;
}
}
It's missing the method type GET, you can do by two options:
#RequestMapping(value = "/{id}", method = RequestMethod.GET)
public User findOne(#PathVariable("id") int id){
return userService.findById(id);
}
OR
#GetMapping("/{id}")
public String getString(#PathVariable("id") int id) {
return "Helloworld";
}
Spring boot Connect with Mysql and get Data.
application.properties
server.contextPath=/demo-user
spring.datasource.url=jdbc:mysql://localhost:3306/testdb
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
*Controller.Java
#RequestMapping({"/users"})
public class UserController {
#Autowired
private UserService userService;
#GetMapping(path = {"/{id}"})
public User findOne(#PathVariable("id") int id){
return userService.findById(id);
}
}
UserService.java
public interface UserService {
User findById(int id);
}
UserServiceImpl.java
#Service
public class UserServiceImpl implements UserService {
#Autowired
private UserRepository repository;
#Override
public User findById(int id) {
return repository.findOne(id);
}
}
UserRepository .java
public interface UserRepository extends Repository<User, Integer> {
User findOne(int id);
}
User.java
#Entity
#Table(name = "user")
public class User {
#Id
#Column
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column
private String firstName;
#Column
private String lastName;
#Column
private String email;
//setter and getter
}
Make request from browser or application.
http://localhost:8080/demo-user/users/1

How to count row table in JPA Query

I'm new to Spring Boot. I have a mysql database, I use a query to count row in my table. But it's not work, it still return my original table data. Can you help me check my code.
Here is my Entity:
#Entity
#Table(name = "act_id_membership", schema = "activiti", catalog = "")
#IdClass(ActIdMembershipEntityPK.class)
public class ActIdMembershipEntity {
private String userId;
private String groupId;
#Id
#Column(name = "USER_ID_")
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
#Id
#Column(name = "GROUP_ID_")
public String getGroupId() {
return groupId;
}
public void setGroupId(String groupId) {
this.groupId = groupId;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ActIdMembershipEntity that = (ActIdMembershipEntity) o;
return Objects.equals(userId, that.userId) &&
Objects.equals(groupId, that.groupId);
}
#Override
public int hashCode() {
return Objects.hash(userId, groupId);
}
}
Here is my query:
#Repository
public interface MemershipRepository extends JpaRepository<ActIdMembershipEntity, String> {
#Query ("select new com.example.activiti_restful.dtos.UserMembership(i.userId, count(i)) from ActIdMembershipEntity i where i.userId ='kermit'")
UserMembership countMemberships(String userId);
}
Updated code:
My service class:
#Service
public class MembershipService {
#Autowired
private MemershipRepository repository;
public long count() {
return repository.count();
}
My resource class:
#RestController
public class MembershipResource {
#Autowired
private MembershipService membershipService;
#GetMapping("/membership")
public long list() {return membershipService.count();}
}
My custom JSON Object class:
public class UserMembership {
private String userId;
private long numberOfusers;
public UserMembership(String userId, long numberOfusers) {
this.userId = userId;
this.numberOfusers = numberOfusers;
}
}
MySQL Table:
act_id_membership
According repositories documentation using CrudRepository provides a method called count() that is one of the Superinterfaces which JpaRepository is implemented.
Based CrudRepository documentation says:
long count(); Returns the number of entities.
Then you should use CrudRepository method. In addition Remove Uppercase MembershipREPOSITORY, by java code convention, you have to use by following way MembershipRepository.
#Repository
public interface MembershipRepository extends JpaRepository <ActIdMembershipEntity, String> {
}
And use it in your Service:
#Service
public class MembershipService {
#Autowired
private MembershipRepository repo;
public long count() {
return repo.count();
}
}
UPDATED
Based on your requirement:
In Controller:
#RestController
public class MembershipResource {
#Autowired
private MembershipService membershipService;
#GetMapping("/membership")
public List<Object> list() { return membershipService.countMemberships();
}
}
In Service:
#Service
public class MembershipService {
#Autowired
private MemershipRepository repository;
public List<Object> countMemberships() {
return repository.countMemberships();
}
}
In Repository:
#Repository
public interface MemershipRepository extends JpaRepository<ActIdMembershipEntity, String> {
#Query ("select i.userId, count(i) from ActIdMembershipEntity i where i.userId ='kermit'")
List<Object> countMemberships();
}
*> Actually I want it return a json format like [{ name: kermit, value:6}]. Now it just return a number 6 only. How I can do that? Thank you!
First, create a class to wrap your data:
public class UserMembership {
private String userId;
private long numberOfUsers;
public UserMembership(String userId, long numberOfUsers) {
this.userId = userId;
this.numerOfUsers = numberOfUsers;
}
}
Then
#Repository
public interface MembershipRepository extends JpaRepository <ActIdMembershipEntity, String> {
#Query ("select new *****.UserMembership(i.userId, count(i)) from ActIdMembershipEntity i where i.userId = :userId")
UserMembership countMemberships(String userId);
}
*****: your full package name
Hope it help!