Dynamic result after error (List or Object) - java

That's my first question, and I've researched but didnt find the answer...
I'm currently developing a REST Webservice using Resteasy. Its working fine but I've come to a doubt: there is a way to return a List OR a Object ?
Let me exemplify: I've got a method to return a LIST of SECTORS that is called after passing a token of authentication.
If the token is OK - It should return the LIST of Sectors.
If the token is not OK - It should return an error which is mapped to a class called ErroGenerico that is an OBJECT.
How can I do that ? Return the OBJECT OR the LIST ?

Make a custom exception ErroGenerico and throw it if the token is not verified.
so, method:
public List<Something> getList(String token) throw ErroGenerico {
// do stuff
}

You can try as below
//Not mandatory to create ListUser you can do without it oo just use arraylist directly
class ListUser extends ArrayList<User> {}
webservice method
#GET
#Path("getObj/{param}")
#Produces("application/json")
public Response getObj(#PathParam("param") String msg) {
ListUser responses = new ListUser();
responses.add(new User("1"));
responses.add(new User("2"));
responses.add(new User("3"));
if("list".equals(msg))
return Response.status(200).entity(responses).build();
User u=new User();
u.setName("Developer");
return Response.status(200).entity(u).build();
}
Client code
Client client = ClientBuilder.newClient();
{
String url = "http://jerseyexample-ravikant.rhcloud.com/rest/jws/getObj/list";
System.out.println(url);
Response response = client.target(url).request().get();
ObjectMapper ob = new ObjectMapper();
Object pojos = response.readEntity(Object.class);
System.out.println(pojos.getClass());
if(pojos instanceof java.util.ArrayList){
ArrayList<User> list = (ArrayList) pojos;
for (Object pojo : list) {
User user = ob.convertValue(pojo, User.class);
System.out.println(user.getName());
}
}else{
System.out.println("user");
User user = ob.convertValue(pojos, User.class);
}
//System.out.println(response);
}
You can check working service at http://jerseyexample-ravikant.rhcloud.com/rest/jws/getObj/list
Here instead of passing list you can pass anything else to get object
In addition to this answer, I've found the article and it worked fine.
resteasy response

Related

Java API / Jersey put method

it's my first API in Java, so please, keep that in mind ;) I've got Controller.class where I'm keeping all my methods right now ( I will clean it later ;) ). As far as GET methods work perfectly I've got problem with PUT method when I want to create new user - it doesn't work. Any help please ? And advices cause - as I said - I'm newbie when it comes to API ;)
So this is my controller.class :
#Path("/api")
public class Controller {
List<Post> mBartoszPosts;
List<Post> mFelipePosts;
List<Post> mShawnPosts;
List<Post> mDavidPosts;
List<Post> mGraziellaPosts;
List<Post> mAllPosts;
List<User> mUsers;
User bartosz;
User felipe;
User shawn;
User david;
User graziella;
#Path("/user/{id}")
#GET
#Produces("application/json")
public Response getUser(#PathParam("id")int id) {
setUpUsers();
System.out.println("Liczba osob : " + mUsers.size());
for(User user : mUsers) {
if(id == user.getId()) {
String result = user.toString();
return Response.status(200).entity(user).build();
}
}
return null;
}
#Path("/post/{post_id}")
#GET
#Produces("application/json")
public Response getPost(#PathParam("post_id")int post_id) {
setUpUsers();
System.out.println("Liczba osob : " + mUsers.size());
for(Post post : mAllPosts) {
if(post_id == post.getId()) {
String result = post.toString();
return Response.status(200).entity(post).build();
}
}
return null;
}
#Path("/posts")
#GET
#Produces("application/json")
public Response getPosts() {
setUpUsers();
String response = new Gson().toJson(mAllPosts );
return Response.status(200).entity(response).build();
}
#PUT
#Path("user/new/{id}/{post}")
#Consumes(MediaType.APPLICATION_XML)
#Produces(MediaType.APPLICATION_XML)
public Response updateEmployeeById(#PathParam("id") Integer id,#PathParam("post") String userPost)
{
List<Post>userPosts = new ArrayList();
Post post = new Post(99,userPost,"Bartosz");
userPosts.add(post);
User updatedEmployee = new User(id,"Bartek","Szlapa",userPosts);
if(updatedEmployee.getName() == null) {
return Response.status(400).entity("Please provide the employee name !!").build();
}
updatedEmployee.setId(id);
updatedEmployee.setName(updatedEmployee.getName());
System.out.println(updatedEmployee.getName());
return Response.ok().entity(updatedEmployee).build();
}
public int maxValue(int array[]){
int max = Arrays.stream(array).max().getAsInt();
return max;
}
}
As you see the last method is PUT and it doesn't work: Here is my test client :
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Client client = ClientBuilder.newClient( new ClientConfig().register( Controller.class ) );
WebTarget webTarget = client.target("http://localhost:8080/JerseyDemos/rest").path("api").path("user").path("new").path("77");
List<Post>userPosts = new ArrayList();
Post post = new Post(99,"Bartek Szlapa","Testing post ...");
userPosts.add(post);
User emp = new User(99,"Bartek","Szlapa",userPosts);
Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_XML);
Response response = invocationBuilder.put(Entity.entity(emp, MediaType.APPLICATION_XML));
User user = response.readEntity(User.class);
System.out.println(response.getStatus());
System.out.println(user);
}
}
And finally my error :
Exception in thread "main" org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=application/xml, type=class entities.User, genericType=class entities.User.
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:248)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:163)
at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1135)
at org.glassfish.jersey.client.ClientRequest.doWriteEntity(ClientRequest.java:516)
at org.glassfish.jersey.client.ClientRequest.writeEntity(ClientRequest.java:498)
at org.glassfish.jersey.client.internal.HttpUrlConnector._apply(HttpUrlConnector.java:384)
at org.glassfish.jersey.client.internal.HttpUrlConnector.apply(HttpUrlConnector.java:282)
at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:278)
at org.glassfish.jersey.client.JerseyInvocation.lambda$invoke$0(JerseyInvocation.java:753)
at org.glassfish.jersey.internal.Errors.process(Errors.java:316)
at org.glassfish.jersey.internal.Errors.process(Errors.java:298)
at org.glassfish.jersey.internal.Errors.process(Errors.java:229)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:414)
at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:752)
at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:445)
at org.glassfish.jersey.client.JerseyInvocation$Builder.put(JerseyInvocation.java:334)
at test.Test.main(Test.java:33)
Thanks in advance for help!
It seems 2 problems in your client code -
For removing this error, you should add jersey-media-jaxb JAR in your classpath. If you are using maven, add below dependency in your pom.xml -
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-jaxb</artifactId>
<version>${jersey.version}</version>
</dependency>
As per your PUT method API specification -
public Response updateEmployeeById(#PathParam("id") Integer id,#PathParam("post") String userPost) {
Your REST service needs only path parameter id and post. No other input is required. However, in your client code, you are sending User class object emp object while calling your API -
Response response = invocationBuilder.put(Entity.entity(emp, MediaType.APPLICATION_XML));
Since you are not receiving this emp object in your API, so this data will get lost. So, either you should update your API for accepting User class object in request or don't sent this object from your client code.

Returning Jersey Response vs Customized POJO Class Object

I am little confused to decide which way is better that, in jersey we can return Response object(jax-rs) and also customized pojo class object.I dont know which way is better and why.can anybody suggest? Please note the return types in both the cases.Here are my two cases.
case 1:
#POST
#Path("/authentication")
public AuthenticationResponse authenticate(#NotNull FITransXTRequest objFITransXTRequest) {
logger.debug("## entering authenticate method");
System.out.println(objFITransXTRequest);
AuthenticationResponse objAuthResponse = new AuthenticationResponse();
JsonObject objResult = objAuthentication.authenticate(objFITransXTRequest);
System.out.println(objFITransXTRequest);
if (objResult != null) {
objAuthResponse.setStan(objResult.get("stan").getAsString());
objAuthResponse.setErrorMessage(objResult.get("responseMsg").getAsString());
objAuthResponse.setStatus(objResult.get("responseCode").getAsString());
objAuthResponse.setUidNumber(objResult.get("uidNumber").getAsString());
objAuthResponse.setRrn(objResult.get("rrn").getAsString());
objAuthResponse.setRdt(objFITransXTRequest.getDt());
}
return objAuthResponse;
}
case 2:
#POST
#Path("/authentication")
public Response authenticate(FITransXTRequest objFITransXTRequest) {
AuthenticationResponse objAuthResponse = new AuthenticationResponse();
JsonObject objResult = objAuthentication.authenticate(objFITransXTRequest);
System.out.println(objFITransXTRequest);
if (objResult != null) {
objAuthResponse.setStan(objResult.get("stan").getAsString());
objAuthResponse.setErrorMessage(objResult.get("responseMsg").getAsString());
objAuthResponse.setStatus(objResult.get("responseCode").getAsString());
objAuthResponse.setUidNumber(objResult.get("uidNumber").getAsString());
objAuthResponse.setRrn(objResult.get("rrn").getAsString());
objAuthResponse.setRdt(objFITransXTRequest.getDt());
}
return Response.ok( objAuthentication.authenticate(objFITransXTRequest)).build();
}
Note: I want to return only one status code that is 200 ok.

Mocking authentication in Spring: List of providers throws NullPointerException

I'm trying to mock authentication in Java for an authentication. This is my test class for mocking the code:
MockitoAnnotations.initMocks(this);
mvc = MockMvcBuilders.standaloneSetup(this.controller).build();
final List<AuthenticationProvider> providers = mock(ArrayList.class);
final AbstractUserDetailsAuthenticationProvider provider = mock(
AbstractUserDetailsAuthenticationProvider.class);
when(provider.supports(any(Class.class))).thenReturn(false);
when(providers.size()).thenReturn(1);
session = new MockHttpSession();
when(providers.get(anyInt())).thenReturn(provider);
when(request.getSession()).thenReturn(session);
when(request.getSession(false)).thenReturn(session);
when(providers.iterator()).thenReturn(new Iterator<AuthenticationProvider>() {
private int currentIndex = 0;
#Override
public AuthenticationProvider next() {
return providers.get(currentIndex++);
}
#Override
public boolean hasNext() {
return currentIndex < providers.size() && providers.get(currentIndex) != null;
}
});
SingleProviderAuthenticationManager manager = new SingleProviderAuthenticationManager(providers);
Map<String, AuthenticationManager> map = new HashMap<String, AuthenticationManager>();
map.put("db", manager);
filter.setAuthenticationManagerMap(map);
when(request.getMethod()).thenReturn("POST");
when(request.getParameter("username")).thenReturn("admin");
when(request.getParameter("password")).thenReturn("admin");
List<User> users = new ArrayList<User>();
User user = new User();
user.setSourceSystem("db");
users.add(user);
when(userService.getUserReferenceByUsername("admin")).thenReturn(users);
auth = filter.attemptAuthentication(request, response);
Now, on the line where I put the manager in the map.put() method, when I put "db" it actually gives the provider manager as null and I get the NullPointerException in the ProviderManager.
for (AuthenticationProvider provider : getProviders()) {
if (!provider.supports(toTest)) {
continue;
}
Even though I've tested the same thing in my main code with the providers I pass its still showing a NullPointerException. And if I put "ldap" instead it gives me a NullPointerException in the UsernamePasswordAuthenticationFilter here:
(last line where the return happens)
password = "";
}
username = username.trim();
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
// Allow subclasses to set the "details" property
setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
I am stuck here, both these things when I pass them are not at all null. Any help?
Don't mock ArrayList instead create new array list and send it to actual class like below :
final List<AuthenticationProvider> providers = new ArrayList<>();
providers.add("AuthenticationProvider object values");
// when(providers.size()).thenReturn(1); -- no need of doing this stuff if you create direct arraylist object.
PS- If you are working with collections, do prefer creating new objects and send that object to actual class instead of mocking and sending, that is the best practice.
Hope it's useful.

Spring-Security : Accessing secured resources using cookie returned at login

I am working on a Java desktop application and after some search I was able to authenticate the user using RestTemplate. Now the situation is I have the cookie String at the desktop side(code given below). Now what I would like to do is to do two important things, get which user logged in using that cookie and access(GET,POST,DELETE) secured resources which are marked with #Secured or #PreAuthorize annotation.
here is my authentication code :
#Override
public void initialize(URL location, ResourceBundle resources) {
submitButton.setOnAction(event -> {
if(!(usernameField.getText().isEmpty() && passwordField.getText().isEmpty())){
try {
RestTemplate rest = new RestTemplate();
String jsessionid = rest.execute("http://localhost:8080/j_spring_security_check", HttpMethod.POST,
new RequestCallback() {
#Override
public void doWithRequest(ClientHttpRequest request) throws IOException {
request.getBody().write(("j_username=" + usernameField.getText() + "&j_password=" + passwordField.getText()).getBytes());
}
}, new ResponseExtractor<String>() {
#Override
public String extractData(ClientHttpResponse response) throws IOException {
List<String> cookies = response.getHeaders().get("Cookie");
// assuming only one cookie with jsessionid as the only value
if (cookies == null) {
cookies = response.getHeaders().get("Set-Cookie");
}
String cookie = cookies.get(cookies.size() - 1);
System.out.println("Cookie is "+cookie);
int start = cookie.indexOf('=');
int end = cookie.indexOf(';');
return cookie.substring(start + 1, end);
}
});
// rest.put("http://localhost:8080/rest/program.json;jsessionid=" + jsessionid, new DAO("REST Test").asJSON());
} catch (AuthenticationException e) {
System.out.println("AuthenticationException");
}
} else {
System.out.println("Fields are empty");
}
});
}
Output of program is :
DEBUG: org.springframework.web.client.RestTemplate - Created POST request for "http://localhost:8080/j_spring_security_check"
DEBUG: org.springframework.web.client.RestTemplate - POST request for "http://localhost:8080/j_spring_security_check" resulted in 302 (Found)
Cookie is JSESSIONID=903B2924CCC84421931D52A4F0AA3C7E; Path=/; HttpOnly
If I was on server-side, I would have simply called the below method to get the currently authenticated user :
#Override
public Person getCurrentlyAuthenticatedUser() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null) {
return null;
} else {
return personDAO.findPersonByUsername(authentication.getName());
}
}
How can I get the currently authenticate user on desktop based java app so I can just use below method and authenticate on desktop java app. :
Collection<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
Authentication authentication = new UsernamePasswordAuthenticationToken(person1, null, authorities);
SecurityContextHolder.getContext().setAuthentication(authentication);
This way, I can use #Secured annotations for the desktop java app as well. Thanks a lot.
Update
So on the server side I have created a method which gives me the logged in user. As suggested in an answer, I can use the same rest template, but I would like to store the cookie in users local db instead of passing the Resttemplates object around when user clicks here and there.
Server side method :
#Secured("ROLE_USER")
#RequestMapping(value = "/rest/getloggedinuser", method = RequestMethod.GET)
public
#ResponseBody
ResponseEntity<RestPerson> getLoggedInRestUser() {
Person person = this.personService.getCurrentlyAuthenticatedUser();
RestPerson restPerson = new RestPerson();
restPerson.setFirstname(person.getFirstName());
restPerson.setUsername(person.getUsername());
restPerson.setPassword("PROTECTED");
return new ResponseEntity<RestPerson>(restPerson, HttpStatus.OK);
}
Now, next for now, I am trying to use the same RestTemplate to check if this method works with code below, but I would really like to know how I can do this with just a cookie :
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add("Cookie", cookie);
HttpEntity requestEntity = new HttpEntity(null, requestHeaders);
ResponseEntity rssResponse = rest.exchange(
"/rest/getloggedinuser",
HttpMethod.GET,
requestEntity,
Person.class);
String rssResponseBody = (String)rssResponse.getBody();
System.out.println("Response body is ");
Is there a way to cast the Object in the ResponseBody to the Person object???
If you want to get some user information which is stored on the server-side, you should create a new service, for example "getUserInformation" on your server, which will provide such information.
You should not extract cookies manually, just reuse the same RestTemplate, it stores cookies internally (specifically in the underlying HttpClient). That's how you can reach secure resources.
UPDATE:
You don't need to pass around the RestTemplate, just make it a singleton and use it everywhere.
And rssResponse.getBody(); should return you a Person object, not String.

Rersteasy exception "No type information to extract entity with, use other getEntity() methods"

I am using resteasy in my project. I am returning an Response object from my rest webfunction.
#Override
public Response getData(#QueryParam(value = "test") String test) {
GenericEntity<List<UserEntity>> customerentities = new GenericEntity<List<UserEntity>>(result){};// result is the List<UserEntity>
return Response.ok(customerentities).build();
}
Now in my junit test case I am doing
Response response = testService.getData("testD");
response.getEntity() // doing this to retrive the List<UserEntity>
But getting the below error
java.lang.RuntimeException: No type information to extract entity with, use other getEntity() methods
at org.jboss.resteasy.client.core.BaseClientResponse.getEntity(BaseClientResponse.java:334)
any idea ?
When using the getEntity() method on the Resteasy client you need to specify the type via <T> parameter, otherwise you need to call one of the other overloaded getEntity() methods that specify the expected return type in the method signature.
ClientRequest request = new ClientRequest('RESOURCE URL HERE');
ClientResponse<List<UserEntity>> response = request.get(new GenericType<List<UserEntity>>(){});
List<UserEntity> users = response.getEntity();

Categories

Resources