Can REST-API controller packaged in JAR be called? - java

I have packaged and deployed my TestRestController.java(PFB code) in a JAR(testrest.jar) in an EAR in JBOSS EAP-6.2,
How can I access my REST-API, i tried hitting the http://{WEB-SERVER-IP}:8080/testrest/test/execute URL from a REST client? But I get HTTP 404.
Is it even possible?
TestRestController.java:
#Path("/test")
public class TestRestController
{
#POST
#Path("/execute")
#Consumes(MediaType.APPLICATION_JSON)
public Response executeRestApi(TestControllerDTO testControllerDto)
{
try
{
if (validateRequestParams(testControllerDto))
{
System.out.println("Validation success.");
response = Response.status(Status.OK).entity("Validation success.").build();
}
else
{
System.out.println("Validation failed.");
response = Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity("Validation failed.").build();
}
}
catch (Exception e)
{
response = Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity("Validation failed.").build();
}
return response;
}
private boolean validateRequestParams(TestControllerDTO testControllerDto)
{
boolean areParamsValid = false;
if (null != testControllerDto)
{
areParamsValid = true;
}
return areParamsValid;
}
}
Please help me.
P.S. : I am a newbie to Java and REST.
Thanks in advance.

You need to initiate the rest servlet somehow. The easiest way is to just add an javax.ws.rs.core.Application with an #ApplicationPath annotation to your application.
#ApplicationPath("/rest")
public class JaxRSApplication extends Application {
}
It can be left empty. It can packaged either in your .jar or in the .war (keep in mind, the .jar should also be included in the war in the WEB-INF/lib). With this the rest servlet will get initialized automatically and the classpath will be scanned for your resource classes annotated with #Path
You can see other deployment options here and for more detailed information, you can see the spec.
With the above Application class, you should be able to access
http://localhost:8080/my-app/rest/test/execute

Related

Spring Boot Creating endpoint for download logs

I created an endpoint in spring boot to download logs of the application:
#Service
public class LogService {
public byte[] obterLog() {
try {
InputStream inputStream = new ClassPathResource("spring.log").getInputStream();
byte[] log = FileCopyUtils.copyToByteArray(inputStream);
return log;
} catch (IOException e) {
throw new FileException(e.getMessage());
}
}
And the controller
#Autowired
private LogService logService;
#GetMapping
public ResponseEntity<byte[]> getLog() {
byte[] log = logService.obterLog();
return ResponseEntity.ok().body(log);
}
But I can only get the log on the second time that I run the application and the log file is on the target/classes folder.
On the first time that I run the application I get a exception:
Class path resource [spring.log] cannot be opened because it does not exist
Why is this happening?
Yes the exception is right. When there are logs, it start printing into .log file and if it is not there, it will create one. In your case you could log something in when the app starts.
You could try something like this and see if the file exist and log something and then try again.
Path path = Paths.get("/path/to/spring.log");
// file exists and it is not a directory
if(Files.exists(path) && !Files.isDirectory(path)) {
log.info("file created");
}

Spring Boot rest controller not working when package in a jar

I am developing a REST API using Spring Boot rest controller. Something strange is happening ; When I test my controller with Eclipse it is working just fine BUT when i deploy the app, packaged in a jar and started with the "java" command line in a docker container then, it doesn't work.
What confuse me is that there is no log. And when I put a sysout at the very beginning of my controller I realized that the controller is not even executed !
Here is the controller with the concerned endpoint, but i am not sure it will help :
#RestController
#RequestMapping("/pdf")
#EnableSwagger2
public class PDFGeneratorResources {
#Autowired
PDFGenerator pdfService;
#Autowired
ResourceLoader resourceLoader;
#PostMapping("/generate-recipies-shoppinglist")
public ResponseEntity<String> generateRecipiesAndShoppingListPDF(#RequestBody List<Day> daysList) {
System.out.println("TRACE");
ResponseEntity<String> responseEntity = null;
String generatedPDFFileURL = "";
try {
generatedPDFFileURL = pdfService.generatePDFFromHTML(PDFTemplates.RecipiesAndShoppingList,
new RecipiesShoppinglistContextBuilder(new ArrayList<Day>(daysList)));
responseEntity = new ResponseEntity<String>(generatedPDFFileURL, HttpStatus.OK);
} catch (Exception e) {
e.printStackTrace();
responseEntity = new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
return responseEntity;
}
}
Question : Is there any way of making spring boot log everything that's happening between tomcat and my controller ? King of --verbose option for spring boot ?
PS:
Here is the DockerFile I am using to deploy the app
FROM registry.gitlab.com/softreaver/meals-ready-backend/runners:centos7jdk11
MAINTAINER MILAZZO_christopher
COPY ./target/*.jar /app.jar
RUN echo -e "/usr/bin/java -Xms128m -Xmx128m -jar /app.jar\n" > /start-app.sh
RUN chmod u+x /start-app.sh
EXPOSE 8080
ENTRYPOINT ["/bin/bash", "/start-app.sh"]
I finally found the problem thx to log.level.root=debug ; I am using the Spring resourceloader to load the template for my PDF service but it seems that it is not able to find the resources folder inside a jar file.
It says : cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/app.jar!/BOOT-INF/classes!/templates/......
I found a solution on internet and made it work by using inputStream :
#Service
public class ResourceLoaderService {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
#Autowired
ResourceLoader resourceLoader;
public String getResourceAbsolutePathString(String location) throws Exception {
Resource resource = resourceLoader.getResource(location);
String absolutePathString = "/";
try {
if (resource.getURL().getProtocol().equals("jar")) {
logger.debug("Jar file system activated");
File tempFile = Files.createTempFile("Mealsready_backend_", null).toFile();
resource.getInputStream().transferTo(new FileOutputStream(tempFile));
absolutePathString = tempFile.getAbsolutePath();
} else {
absolutePathString = resource.getFile().getAbsolutePath();
}
} catch (IOException e) {
logger.error("Error while trying to retrieve a resource : " + e.getMessage());
// TO DELETE Remplacer par un ServiceException
throw new Exception();
}
return absolutePathString;
}
}

Multiple war deployment Tomcat without blocking

I have one unique instance with three war :
Aapp.war
Bapp.war
Capp.war
The Capp need a wsdl endpoint exposed by the Bapp.
I know it's not great, but I need to find a temporary solution without a big refactoring in existing architecture.
The problem is even if the Aapp.war and Bapp.war are deployed, when tomcat begin to deploy the Capp, it lock everything because the bean which instanciate the Bapp Wsdl client does not respond :
#Bean
public WsStorageService getCustomerOfferStorageWSClient(){
WsStorageService wsClient = null;
String wsdlUrlProperty = prop.getCosWSApplicationServicesUrl();
URL url = null;
try {
url = new URL(wsdlUrlProperty);
} catch (MalformedURLException e) {
e.printStackTrace();
}
wsClient = new WsService_Service(url).getWsServicePort();
return wsClient ;
}
I cannot call http://myserver/Aapp or http://myserver/Bapp until the Capp is deployed successfully.
Why ?

Azure deployement seems not working with my web-service in Java EE with IntelliJ and Azure tools

I did a webservice in Java EE in SCRUD. I try to put it on Azure web-app because I would like to use it for another project and it will be easier if I can put it on it. But when I deploy it on Azure, I only have acces at the index.jsp page.
My classes are like that:
#Path("LikePost")
public class LikePostAPI extends RestApplication {
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("GetAll")
public Response getAll(){
Connection conn= GetConnection.getInstance().getConnection();
Response response= Response.status(Response.Status.OK).entity(new DaoLikePost(conn).getAll()).build();
return response;
}
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("getLike")
public Response getLike(#QueryParam("id") int id) {
Response response=null;
Connection conn=GetConnection.getInstance().getConnection();
Like l=new DaoLikePost(conn).find(id);
if(l!=null)
response=Response.status(Response.Status.OK).entity(l).build();
else
response=Response.status(Response.Status.NO_CONTENT).entity(null).build();
return response;
}
#POST
#Produces(MediaType.APPLICATION_JSON)
#Path("CreateLike")
public Response createLike(#FormParam("dateLiked") String dateLike,#FormParam("user") String userId,#FormParam("post") String postId){
Connection conn=GetConnection.getInstance().getConnection();
Like l=new Like();
l.setUser(new DaoUser(conn).find(Integer.parseInt(userId)));
DateFormat dateFormat=new SimpleDateFormat("yyyy-mm-dd hh:mm:ss");
Date date=null;
try {
date=dateFormat.parse(dateLike);
} catch (ParseException e) {
e.printStackTrace();
}
l.setDateLiked(date);
l.setPost(new DaoPost(conn).find(Integer.parseInt(postId)));
Boolean test=new DaoLikePost(conn).create(l);
Response response=null;
if(test)
response=Response.status(Response.Status.OK).entity(test).build();
else
response=Response.status(Response.Status.BAD_REQUEST).entity(test).build();
return response;
}
#DELETE
#Path("DeleteLike")
#Produces(MediaType.APPLICATION_JSON)
public Response deleteLike(#QueryParam("id")int id){
Connection conn=GetConnection.getInstance().getConnection();
Like l=new DaoLikePost(conn).find(id);
Boolean test=new DaoLikePost(conn).delete(l);
Response response=null;
if(test)
response=Response.status(Response.Status.OK).entity(test).build();
else
response=Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(null).build();
return response;
}
#PUT
#Path("UpdateLike")
#Produces(MediaType.APPLICATION_JSON)
public Response updateLike(#FormParam("id") String idLike,#FormParam("dateLiked") String dateLike,#FormParam("user") String userId,#FormParam("post") String postId){
Connection conn=GetConnection.getInstance().getConnection();
Like l=new Like();
l.setId(Integer.parseInt(idLike));
l.setUser(new DaoUser(conn).find(Integer.parseInt(userId)));
Date date=null;
DateFormat dateFormat=new SimpleDateFormat("yyyy-mm-dd hh:mm:ss");
try {
date=dateFormat.parse(dateLike);
} catch (ParseException e) {
e.printStackTrace();
}
l.setDateLiked(date);
l.setPost(new DaoPost(conn).find(Integer.parseInt(postId)));
Boolean test=new DaoLikePost(conn).update(l);
Response response=null;
if(test)
response=Response.status(Response.Status.OK).entity(test).build();
else
response=Response.status(Response.Status.BAD_REQUEST).entity(null).build();
return response;
}
}
here's the configuration for the deployement: https://gyazo.com/fed4d79d5d3cb72a820073efd234feb2
for the artifacts exploded: https://gyazo.com/a948f72cff3b89fd86df7d820aa928eb
and for the war file: https://gyazo.com/7ac6ead33bd6a129a4ad2a7ec537acd0
The Azure website is: https://faceapibook.azurewebsites.net/
First of all, without Azure using IntelliJ, you have to make sure your application will be running normally in Tomcat or Jetty on your local machine.
Then you can follow the two offical tutorials below to directly deploy it to Azure in your IntelliJ with Azure Toolkit plugin.
Create a Hello World web app for Azure using IntelliJ
Publish a Spring Boot app as a Docker container by using the Azure Toolkit for IntelliJ
Besides, if you can make your exported war file works in your local tomcat server, you also can follow the section Deploy WAR file of the offical document Deploy your app to Azure App Service with a ZIP or WAR file to deploy the war file exported from your IntelliJ project, and see more details from the wiki page Deploying WAR files using wardeploy.
Even, when you correctly set the value of Java version in the tab Application settings of Azure portal, as below, you can upload the war file into the webapps directory under the path wwwroot of Kudo console directly to complete the deployment.

open a file in a tomcat webapplication

i want to open a file and return its content. Although it is in the same directory like the class that wants to open the file, the file can't be found. Would be cool if you could help me solving the problem.
Here is the code:
#GET #Produces("text/html") #Path("/{partNO}/") #Consumes("text/html")
public String getPartNoResponseHTML(#PathParam("partNO") String parID) throws WebApplicationException {
PartNoTemplate partNo = getPartNoResponse(parID);
String result = "";
try {
result = readFile(PART_NO_TEMPLATE_FILE);
} catch (FileNotFoundException e) {
e.printStackTrace(System.out);
return e.getMessage() + e.toString();
// throw new WebApplicationException(Response.Status.NOT_FOUND);
} finally {
result = result.replace("{partNO}", parID);
result = result.replace("{inputFormat}", partNo.getFormat().toString());
}
return result;
}
I guess it can't find the file, because its running on tomcat. I'm also using Jersey and JAX-RS. Thank you for your help,
Maxi
If the file is inside the application WAR (or in a jar) you can try by using
InputStream input = servletContext.getClass().getClassLoader().getResourceAsStream("my_filename.txt");
Your problem is similar (I think) with How can I read file from classes directory in my WAR?
Try to get the path of the file from ServletContext.
ServletContext context = //Get the servlet context
In JAX-RS to get servlet context use this:
#javax.ws.rs.core.Context
ServletContext context;
Then get the file from your web application:
File file = new File(context.getRealPath("/someFolder/myFile.txt"));
You don't post the code that actually tries to read the file, but assuming the file is in the classpath (as you mention it's in the same directory as the class) then you can do:
InputStream in = this.getClass().getResourceAsStream("/SomeTextFile.txt");
See here

Categories