Multiple functions for the same path in jax.ws.rs? - java

Lets say I wanted in implement readonly behaviour on my application (not allowing posts/puts). Could I do this by disabling these types/setting a #POST/#PUT that catches requests on any endpoint? (As opposed to putting a boolean flag on every single post/put in my application

You could add a filter, disallowing all the methods you don't want to support:
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.ext.Provider;
#Provider
public class AuthorizationRequestFilter implements ContainerRequestFilter {
private final List<String> disallowed=Arrays.asList("POST","PUT","DELETE","PATCH");
#Override
public void filter(ContainerRequestContext requestContext)
throws IOException {
if (disallowed.contains(requestContext.getMethod())){
requestContext.abortWith(Response
.status(Response.Status.FORBIDDEN)
.entity("User cannot modify the resource.")
.build());
}
}
}

Related

Initialize Hats methods using GenericPortlet class

I am replacing PortletAdapter with GenericPortlet class in code. I followed this link - https://help.hcltechsw.com/digital-experience/9.5/dev-portlet/jsrmig.html. I am trying to initialize HATS-Host Access Transformation Services methods (see initializeHats() method) and it needs ServletConfig as a parameter. But I am not able to access the getServletConfig() method in the GenericPortlet class. I passed getPortletConfig() but got a null pointer exception. Below are my old code and new code. What is the replacement for the getServletConfig()?
Old code:
package abcpostavailablefreight;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import org.apache.jetspeed.portlet.*;
import org.apache.jetspeed.portlet.event.*;
import com.ibm.hats.runtime.connmgr.Runtime;
import com.ibm.hats.util.LicenseManager;
public class AbcPostAvailableFreightPortlet extends PortletAdapter implements ActionListener {
public void init(PortletConfig portletConfig) throws UnavailableException {
super.init(portletConfig);
}
public void initializeHats() {
initHATS = true;
//Initialize and activate the HATS runtime RAS functions,
// including tracing, logging, PII retrieval, locale.
com.ibm.hats.util.Ras.initializeRas(getServletConfig());
//Create the license manager
LicenseManager.getInstance();
//Initialize Host Publisher/connection management runtime
Runtime.initRuntime(getServletConfig());
}
}
New Code:
package abcpostavailablefreight;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import javax.portlet.*;
import javax.portlet.UnavailableException;
import javax.servlet.*;
import javax.servlet.http.HttpSession;
public class AbcPostAvailableFreightPortlet extends GenericPortlet{
public void init(PortletConfig portletConfig) throws UnavailableException, PortletException {
super.init(portletConfig);
}
public void initializeHats(ActionRequest request) {
initHATS = true;
//Initialize and activate the HATS runtime RAS functions,
// including tracing, logging, PII retrieval, locale.
com.ibm.hats.util.Ras.initializeRas(getPortletConfig());
//Create the license manager
LicenseManager.getInstance();
//Initialize Host Publisher/connection management runtime
Runtime.initRuntime(getPortletConfig());
}
}

Spring Boot REST API app, testing Controller layer with JUNIT

hi i am learning Java and Spring Framework, i don't even consider myself beginner. The other day i found great study material "Spring-Boot Masterclass". I am learning from this source, first part was about making simple REST API CRUD application with custom methods, custom exceptions, by using MySQL database. I've learned a lot from this source, and everything went smooth, i understood everything till now, i am at testing repository, service and controller layers. I managed to create tests for CRUD methods + few custom methods for all 3 layers, and all tests passed with green result in Eclipse, i just stopped at void deleteMinisterstvo() method. Question is in Controller Layer above mentioned method in comment, but i'll share it here too, because i am getting lost:
HOW is this working, when i create database record with id=15, then delete ID=4 from endPoint for ID= 55, and TEST passes? Which one is being deleted then?
Maybe i did not even write method as it should be written, so i would like to ask you, experienced developers on your opinion, idea, maybe explanation. Thanks
*Note1: I started this thread with Hi, i... but it somehow did not save, so i tried to edit and even edit does not give Hi there. Sorry for that.
*Note2: I removed all other methods (commented them out) from Repository, Service and Controller layers for focusing only at deleteMethod. I thought, that this test should not pass, but throw error:
Project
MinisterstvoRepository
package com.Ministerstvo.Repository;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import com.Ministerstvo.Model.Ministerstvo;
#Repository
public interface MinisterstvoRepository extends JpaRepository<Ministerstvo, Long>{
}
MinisterstvoService
package com.Ministerstvo.Service;
import java.util.List;
import com.Ministerstvo.Exceptions.MinisterstvoNotFoundException;
import com.Ministerstvo.Model.Ministerstvo;
public interface MinisterstvoService {
void odstranMinisterstvo(Long id) throws MinisterstvoNotFoundException;
}
MinisterstvoServiceImpl
package com.Ministerstvo.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.Ministerstvo.Controller.MinisterstvoController;
import com.Ministerstvo.Exceptions.MinisterstvoNotFoundException;
import com.Ministerstvo.Model.Ministerstvo;
import com.Ministerstvo.Repository.MinisterstvoRepository;
import lombok.AllArgsConstructor;
import lombok.Data;
#Service
#Data
#AllArgsConstructor
public class MinisterstvoServiceImpl implements MinisterstvoService {
#Autowired
private final MinisterstvoRepository ministerstvoRepository;
private final Logger LOGGER = LoggerFactory.getLogger(MinisterstvoController.class);
#Override
public void odstranMinisterstvo(Long id) throws MinisterstvoNotFoundException {
LOGGER.info("Metoda odstranMinisterstvo() v MinisterstvoServiceImpl");
Optional<Ministerstvo> ministerstvo = ministerstvoRepository.findById(id);
if(!ministerstvo.isPresent()) {
throw new MinisterstvoNotFoundException("Ministerstvo so zadanym ID neexistuje...");
}
ministerstvoRepository.deleteById(id);
}
}
MinisterstvoController
package com.Ministerstvo.Controller;
import java.util.List;
import javax.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.Ministerstvo.Exceptions.MinisterstvoNotFoundException;
import com.Ministerstvo.Model.Ministerstvo;
import com.Ministerstvo.Service.MinisterstvoService;
import lombok.AllArgsConstructor;
import lombok.Data;
#RestController
#Data
#AllArgsConstructor
public class MinisterstvoController {
#Autowired
private final MinisterstvoService ministerstvoService;
private final Logger LOGGER = LoggerFactory.getLogger(MinisterstvoController.class);
// API - DELETE
#DeleteMapping("/ministerstva/{id}")
public ResponseEntity<String> odstranMinisterstvo(#PathVariable("id") Long id) throws MinisterstvoNotFoundException {
LOGGER.info("Metoda odstranMinisterstvo() v MinisterstvoController");
ministerstvoService.odstranMinisterstvo(id);
return new ResponseEntity<String>("Uspesne odstranene ministerstvo", HttpStatus.OK);
}
}
MinisterstvoControllerTest
package com.Ministerstvo.Controller;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.util.List;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import com.Ministerstvo.Model.Ministerstvo;
import com.Ministerstvo.Service.MinisterstvoService;
import com.fasterxml.jackson.databind.ObjectMapper;
#WebMvcTest
#ExtendWith(MockitoExtension.class)
class MinisterstvoControllerTest {
#Autowired
private MockMvc mockMvc;
#MockBean
private MinisterstvoService ministerstvoService;
Ministerstvo ministerstvo;
List<Ministerstvo> zoznamMinisterstiev;
#BeforeEach
void setUp() throws Exception {
ministerstvo = Ministerstvo.builder()
.ministerstvoId(6L)
.ministerstvoName("MinisterstvoKultiry")
.ministerstvoEmail("kultura#gmail.com")
.ministerstvoPocetZamestnancov(5)
.build();
}
#AfterEach
void tearDown()
{
ministerstvo = null;
}
// DELETE TEST
// HOW IS THIS WORKING, WHEN I CREATE DB RECORD WITH ID 15, then delete ID 4 from endPoint for ID 55, and TEST passes?
#Test
void deleteMinisterstvo() throws Exception
{
Ministerstvo ministerstvoNadstranenie = Ministerstvo.builder()
.ministerstvoId(15L)
.ministerstvoName("Ministerstvo of Nothing")
.ministerstvoEmail("nothing#gmail.com")
.ministerstvoPocetZamestnancov(789)
.build();
doNothing().when(ministerstvoService).odstranMinisterstvo(4L);
// same result as from doNothing() above //doNothing().when(ministerstvoService).odstranMinisterstvo(ministerstvo.getMinisterstvoId());
// same result as from mockMvc.perform() below
//mockMvc.perform(delete("/ministerstva/55")
mockMvc.perform(delete("/ministerstva/"+ ministerstvoNadstranenie.getMinisterstvoId().toString())
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andDo(print());
}
}
If i forgot to provide more details, i will add them based on instructions. I am just curious, if test for delete method is working properly, would be great to know the way, why test passes with different data.
Thanks for reading,
have a nice day

How to wire classes and objects in SpringBoot

Have SpringBoot Java app with different classes. I am not able to inject the dependencies and initialize/access the object of one class into another . Have seen the spring doc and used the annotations (#component,#Autowired etc. ), still there is an issue.
following are the classes.
Main Class ()
package com.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;
#SpringBootApplication
public class CostmanagementApplication {
public static void main(String[] args) {
SpringApplication.run(CostmanagementApplication.class, args);
}
}
Controller class
package com.test;
import javax.swing.text.rtf.RTFEditorKit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
#Component
#Controller
public class HighChartsController {
#Autowired
private RequestToken rt;
#GetMapping("/costdata")
public static String customerForm(Model model) {
//here not able to access the getToken() method
model.addAttribute("costdata", new CostDataModel());
return "costdata";
}
}
RequestToken Class
package com.test;
import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpRequest.BodyPublishers;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap;
import java.util.stream.Collectors;
import org.json.JSONObject;
import org.springframework.stereotype.Component;
#Component
public class RequestToken {
public String getToken() throws IOException, InterruptedException {
// TODO Auto-generated method stub
// code to get the token
return token;
}
}
now eventhough , I have all annotation in place , not getting why the getToken() method is not accessible in controller class using rt object. please suggest
Okay, let's go in order.
First of all, all the annotations #Service, #Controller and #Repository are specifications from #Component, so you don't need to specify #Component and #Controller in your HighChartsController.
Actually, if you check what the annotation #Controller definition is, you'll find this:
#Component
public #interface Controller {
...
}
Secondly, I don't really know what do you mean with that you aren't able to access the getToken() method, but as you wrote it seems you tried to access to that method as an static method.
You're injecting the object, so you use the methods of the objects like in plain Java: rt.getToken(). The only difference is that the RequestToken object will be already initialized at the moment you call it.
package com.test;
import javax.swing.text.rtf.RTFEditorKit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
#Controller
public class HighChartsController {
#Autowired
private RequestToken rt;
#GetMapping("/costdata")
public static String customerForm(Model model) {
String token = rt.getToken();
...
model.addAttribute("costdata", new CostDataModel());
return "costdata";
}
}

Request url path in jax-rs

so i have this jax-rs REST project and ive never used jax in my life.
what id like to do (probably not the right way) is when someone requests something from my api they should
type url.com/token/path/sub-path/
id like to collect the : /token/path/sub-path/ part, even better put it in an array like this :
[token,path,sub-path]
the project says i should use filters. i also have another issue where when im in the filter class i dont know how to output data, to either the web page or even my eclipse console.
package com.di3;
import java.io.IOException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriInfo;
import com.di3.admin.AdminHandler;
public class LoginFilter implements ContainerRequestFilter{
#Context
#Override
public void filter(ContainerRequestContext request) throws IOException {
// TODO Auto-generated method stub
//do some token checking!
System.out.println(token);
}
}
thank you very much and sorry if the questions are silly or something.

How to test RESTful application?

I have an application example with a service:
RestApp.java
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("/webapi")
public class RestApp extends Application {
#Override
public Set<Class<?>> getClasses() {
final Set<Class<?>> classes = new HashSet<>();
classes.add(MessageService.class);
return classes;
}
}
MessageService.java
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.net.URI;
import java.util.List;
#Stateless
#Path("/messages")
public class MessageService {
#Inject
private MessagesManager messagesManager;
#GET
#Path("all")
#Produces({MediaType.APPLICATION_JSON})
public List<Message> getMessages() {
return messagesManager.getMessages();
}
}
and the service depends on the singleton MessagesManager.java:
import javax.ejb.*;
import javax.inject.Singleton;
#Singleton
#Startup
#ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class MessagesManager implements Serializable {
private List<Message> messages = new ArrayList<>();
#Lock(LockType.READ)
public List<Message> getMessages() {
messages.add(new Message(1, "message text"));
return messages;
}
}
and this app works fine. But during the test occurs error of injection:
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=MessagesManager,parent=MessageService,qualifiers={},position=-1,optional=false,self=false,unqualified=null,1232089028)
Test code is:
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Response;
import static org.junit.Assert.assertEquals;
public class RestAppTest extends JerseyTest {
#Override
protected Application configure() {
return new ResourceConfig(MessageService.class);
}
#Test
public void testGet() {
final Response response = target("messages/all").request().get();
assertEquals(200, response.getStatus());
}
}
Why it happens and how to fix it?
The class MessagesManager is missing in an application context. Add the class to configure method like this:
return new ResourceConfig(MessageService.class, MessagesManager.class);
You need couple of things
1> Well formed JSON structure for your REST API
2> Some kind of REST client such as advanced REST client for chrome, Mozilla etc which can be used as a plugin. POSTMAN is also a useful tool

Categories