Spring Java mulipart data file save - java

I work with Spring.
I have this code on my controller
#Controller
public class FileUploadController {
#RequestMapping(value = "/file-upload", method = RequestMethod.POST)
#ResponseBody
public String uploadFile(#RequestParam("file") MultipartFile file, HttpServletRequest request,ServletContext context) throws IOException {
if(!file.isEmpty()) {
file.transferTo(new File("/data.xml"));
return "ok";
}
else {
return "Empty";
}
}
}
i just want to save the uploaded file to the root directory.
It seem to me that i use a absolute Path to the Root, but i don't now how i can find that out.
Can anybody help me ?

You can get real path with
HttpServletRequest.getSession().getServletContext() but this will be helpful If your application has session.If your application is sessionless than you can do by implementing ServletContextAware.
If application has session then
request.getSession().getServletContext().getRealPath("WEB-INF");
also one another way to get real path.

Get the class loader from one of your objects and use that to get its local path. That will give you a path from your execution point in Tomcat. From there you can find the location you want.
obj.getClass().getResource("/");

Related

Spring Boot. Forward on RestController

I am implementing a mechanism for replacing short links.
I need to forwarded request to another controller. I found examples how to do it in spring on models, but I don't understand how to do it in RestControllers
Example what i found (use models)
#Controller
public class ShrotLinkForwardController {
#RequestMapping("/s/*")
public String myMethod(HttpServletRequest request) {
return "forward:/difmethod";
}
}
Or maybe I'm looking in the wrong direction and I need to make a filter?
UPD. I don't know the final endpoint, it is calculated in the forwarded method. So, i cant autowired other controller
There are 2 ways to achieve what you want.
1. Call the method on the target controller directly.
Controllers are just normal Spring beans. You can get it via autowire.
#Controller
public class ShrotLinkForwardController {
#Autowired
OtherController otherController;
#RequestMapping("/s/*")
public String myMethod(Model model) {
otherController.doStuff();
return ...;
}
}
2. Trigger the forward by returning a string
To trigger the forward, try returning a String instead of ModelAndView.
This is the approach you mentioned in your question. Note that the syntax should be forward:/forwardURL. The string after forward: is the URL pointing to another controller, not the method name.
#Controller
public class ShrotLinkForwardController {
#RequestMapping("/s/*")
public String myMethod(Model model) {
return "forward:/forwardURL";
}
}
you could inject the target controller and simply call the method
#Controller
public class ShortLinkForwardController {
#Autowired
private RestController target;
#RequestMapping("/s/*")
public String myMethod(HttpServletRequest request) {
return target.myMethod(request);
}
}
Caveat: Path related request properties will still point to "/s/*"
Or use ResponseEntity and set target location...
public ResponseEntity<Void> myMethod(HttpServletRequest request) {
return ResponseEntity.status(302).location(URI.create(...)).build();
}
All answers are about returning String
But I've found another solution
Maybe it will help someone with my problem in case when you need to make forward from one REST endpoint to another REST endpoint.
And it also could be applied to your case.
#RestController
public class CustomerController {
#GetMapping("/forwarding_endpoint")
public void makeForward(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getSession().getServletContext().getRequestDispatcher("/forward_endpoint").forward(request, response);
}
}
UPD. I don't know the final endpoint, it is calculated in the
forwarded method. So, i cant autowired other controller
but I don't understand how to do it in RestControllers
I can see some indications of possible bad design here, so I will try to explain the possible issues and how should be handled according to best practices.
If your requirement is to make a forward to another controller, then this might be an indication of 3 possible issues:
The job to be done by the other controller (which you say you want to forward to) can be extracted into a service method in service layer. Then both controllers can call the same service method, without each controller be aware of the other.
Your need could also be an indicator of the following issue. You need 2 controllers for exactly the same practical reason, so that they provide for same input exactly the same output, but to be available from 2 different URLs. If this is the case then you can use just 1 controller and allow it to be executed for both URLs. See the following code to achieve this:
#RequestMapping({"/s/*", "/s2/*})
public String myMethod(HttpServletRequest request) {
return "some response";
}
You need to expose only 1 URL to the client which will serve everything. Then the approach with forward will also not benefit you, since the client will be able to reach the other forwarded controller directly if he wishes so. In this case you can implement 1 single controller which then according to the needs builds different responses. You can do this in RestController although not suggested by Sonar and other code review tools by marking the method to return ResponseEntity<?>. Example:
#RequestMapping("/s/*")
public ResponseEntity<?> myMethod(HttpServletRequest request) {
if (condition 1) {
return new ResponseEntity<YourObject1>(HttpStatus.OK);
} else if (condition 2) {
return new ResponseEntity<YourObject2>(HttpStatus.OK);
} else {
return new ResponseEntity<YourObject3>(HttpStatus.OK);
}
}
this last choice is not considered best practice with <?> but for this requirement I don't see any other way out.

Changing restAPI URI

I have created an application in java with the name hello. my class is below
#Path("/test")
class TestAPI
{
#GET
#Path("/hi")
public String sayHi()
{
return "Hi I am Shweta";
}
}
I am accessing this application using
GET http://localhost:8080/hello/test/hi
Is there anyway I can remove hello from URI or I can replace the same without changing application.
If I need to access like http://localhost:8080/test/hi what changes I need to do? I am using maven.
Yes you can do it in your server.Say if you are using tomcat to deploy your application,Then go through its configuration file and change the context path to '/'.It will work.You just need to check where context path is defined in what ever server you are using and just replace the path with '/'.

Get the Path of a resource from a spring boot aplication using servlet context

I have this structure, generated by spring boot
So I want to get a input stream of the file gastos.xlsx using sevletContext.
#Autowired
private ServletContext context;
#GetMapping("/grafico")
public ResponseEntity<String> exportExcelGrafico(HttpServletResponse response){
try{
//this path returns null. What is the real path to put here?
InputStream input = context.getResourceAsStream("src/main/resources/templates/gastos.xlsx");
//returns null
input = context.getResourceAsStream("/resources/templates/gastos.xlsx");
// Returns null
input = context.getResourceAsStream("/templates/gastos.xlsx");
}
catch(){
}
What would be the right path?
I didn't configure anything on my application.properties
What's in the src/main/resources folder of your Maven or Gradle project ends up in your jar, not in the web resources. And it should thus be loaded using the class loader, not using the servlet context:
MyClass.class.getResourceAsStream("/templates/gastos.xlsx")
Not sure why you put that file under templates, since... it's not a template.

How to add a file to upload in message flow of Mule ESB?

This is my Controller use SpringMVC, it has 2 params is "file" and "fileDesc":
#RequestMapping(value = "/uploadfiles", method = RequestMethod.POST)
#ResponseBody
public String createResource(#RequestParam("file") MultipartFile[] files, #RequestParam("fileDesc") String fileDesc, Locale locale)
throws IOException, ServiceProcessException {...}
And this is my design in Mule:
I don't know how to get files to get value in controller because data I send to Mule then point to Controler in runtime.
A similar use case has been discussed here.
HTH.

How to reach the WebContent folder from a web service method

I want to reach a file in WebContent folder from a method in a web service in the same project. For example:
#WebMethod
public String test() {
File configFile = new File("config.xml");
return configFile.getAbsolutePath();
}
It returns "/usr/share/glassfish3/glassfish/domains/domain1/config/config.xml". I want to get to a file in the directory "/usr/share/glassfish3/glassfish/domains/domain1/applications/my_project_name/" folder. How can I get to it?
The best way to do this that I use is:
Thread.currentThread().getContextClassLoader().getResource("myFile.txt").getPath()
This gives the path of any file myFile.txt placed in /WEB-INF/classes/ directory inside the WebContent folder of the WebApp.
In Eclipse JEE environment you need to keep the file myFile.txt, that you may want to read within the Web Service, in the src folder for it to be transported to the /WEB-INF/classes/ folder by the deployer.
From your code, I understand that yours is an JAXWS webservice.
In jaxws, you can get the HttpServletRequest, HttpServletResponse, ServletContext,
Have a private variable in your webservice class and annotate it in this way
#Resource
private WebServiceContext context;
And then in your method, you can get the ServletContext this way
ServletContext servletContext =
(ServletContext) context.getMessageContext().get(MessageContext.SERVLET_CONTEXT);
From servletContext, you can get the path.
Suppose if you need to get HttpServletRequest, you can get it in this way
HttpServletRequest request =
(HttpServletRequest) context.getMessageContext().get(MessageContext.SERVLET_REQUEST);
and you can get the context path of your app like
request.getContextPath() ;
Add the following parameter to your web service class:
#Context
ServletContext context;
Then, supposing your config.xml file is in the WebContent folder, you can get its absolute path by invoking the method context.getRealPath(String). Using your example code it would be:
#WebMethod
public String test() {
File configFile = new File(context.getRealPath("config.xml"));
return configFile.getAbsolutePath();
}
Or directly, without passing by a File object:
#WebMethod
public String test() {
return context.getRealPath("config.xml");
}

Categories