I am creating an application and want to send user data along with his profile picture. I am using reactjs for frontend and java 1.8 with spring boot 2.3.1. I researched for 3 days and everywhere I see that we can send the user data and profile picture file as multipart form data from UI and then do the following in my controller to get the two different data.
public ResponseEntity<String> saveUser(#RequestParam("user") String stringUserRequest, #RequestParam("file") MultipartFile file)
Here the user data is actually a JSON but is converted to a string and sent from UI.
But this keeps throwing the below error
org.springframework.web.multipart.MultipartException: Failed to parse multipart servlet request; nested exception is java.lang.IllegalStateException: Unable to process parts as no multi-part configuration has been provided
I have searched a lot and it has something to do with the servelet version being higher than 3.0. There are a lot of questions regarding the same but all of them are for spring framework and not for spring boot in particular and have tried them also but nothing seems to work.
Can anyone tell me either how to create this Multipart Config for spring boot or how to degrade the servelet version?
You need to configure a multipart resolver in your configuration class, first you add these dependencies in your POM:
<!-- multipart resolver-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
and you need to declare this Bean configuration:
#Bean(name = "multipartResolver")
public CommonsMultipartResolver multipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
return multipartResolver;
}
Finally, don't forget to specify the content type as multipart/form-data when sending your request.
EDIT:
the header Content-type should be multipart/form-data;boundary=--------------------------362947062764690924037801
Related
Small question regarding some actuator endpoints returning 404 please.
I have a web app, based on Webflux 2.4.2, and for testing this issue only, I am using
management.endpoints.web.exposure.include=*
Actuator is working, because a curl will get the response for /health /metrics and other endpoints.
However, for those endpoints /auditevents /httptrace /integrationgraph /sessions, I am not able to get anything, besides a http 404.
[05/Feb/2021:13:00:18 +0000] "OPTIONS /auditevents HTTP/1.1" 404 141 55 ms
May I ask what did I miss please?
What are the steps to enable the /auditevents endpoint please?
What are the steps to enable the /httptrace endpoint please? I have sleuth and Zipkin working
What are the steps to enable the /integrationgraph endpoint please?
What are the steps to enable the /sessions endpoint please?
Those are really the only endpoints returning 404, still do not know why.
Don't want to spam with one question same question per endpoint. All other actuator endpoints are fine.
Thank you
According to Spring Boot Reference Docs :
To enable /httptrace in the actuator, then you have to create a bean of InMemoryHttpTraceRepository class in the custom #Configuration class which provides the trace of the request and response.
#Bean
public HttpTraceRepository htttpTraceRepository() {
return new InMemoryHttpTraceRepository();
}
To enable /auditevents in the actuator, then you have to create a bean of InMemoryAuditEventRepository class in the custom #Configuration class which exposes audit events information.
#Bean
public AuditEventRepository auditEventRepository() {
return new InMemoryAuditEventRepository();
}
To enable /integrationgraph in actuator, you have to add spring-integration-core dependency in the pom.xml (as per documentation) :
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
</dependency>
or if you are having a spring-boot project, then add this :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-integration</artifactId>
</dependency>
/actuator/sessions are by-default enabled. But still you can add this explicitly to check the behaviour.
Add this in application.properties.
management.endpoint.sessions.enabled = true
I'm trying to in corporate Spring Actuator to my application. I have added the dependency in my pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>1.4.2.RELEASE</version>
</dependency>
But I get a 404 when trying to access the /health endpoint. After looking online, I've read that I need to also have the spring-boot-starter-web dependency in my POM. I was under the assumption that I only need the actuator dependency in order to get it working
Yes web is needed if you want to access via HTTP (otherwise only JMX is available).
The documentation for actuator states
"Click Dependencies and select Spring Web and Spring Boot Actuator."
Need to Integrate Camel and MyBatis with application using SpringBoot.
SpringBoot provides out-of-box support for Camel and MyBatis. Also provides Camel and MyBatis SpringBoot starters.
However, when i try to integrate Spring Boot application with Camel and MyBatis, it fails.
I am using Java DSL based Camel Route. Also using Mybatis Spring boot dependencies. Annotate mappers, added database properties in the application.properties file. What I was expecting to happen:
1) SpringBoot setup datasource and mappers, sqlsessionfactory on start-up.
2) Next the Camel-MyBatis consumer is called, the setup done in (1) would allow, Camel to successfully make database calls using mybatis.
I created spring annotated configuration class and used it to create/get DataSource bean.
How can i get Camel to use this dataSource bean?
How to tell Camel to use newly build SQL session factory, instead of it trying to build from configuration file?
Created sample appl in github, its using in-memory db (h2)
sample-app
Getting NPE
Consumer[mybatis://getClaimInfo?statementType=SelectOne] failed polling endpoint: Endpoint[mybatis://getClaimInfo?statementType=SelectOne]. Will try again at next poll. Caused by: [org.apache.ibatis.exceptions.PersistenceException -
Error opening session. Cause: java.lang.NullPointerException
Cause: java.lang.NullPointerException]
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30) ~[mybatis-3.4.0.jar:3.4.0]
at org.apache.ibatis.session.defaults.DefaultSqlSessionFactory.openSessionFromDataSource(DefaultSqlSessionFactory.java:100) ~[mybatis-3.4.0.jar:3.4.0]
at org.apache.ibatis.session.defaults.DefaultSqlSessionFactory.openSession(DefaultSqlSessionFactory.java:47) ~[mybatis-3.4.0.jar:3.4.0]
I have been able to use Spring Boot 1.3.6, Apache Camel 2.17.2 with Mybatis-Spring-Boot-Starter 1.1.1 successfully:
Key dependencies in maven:
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-mybatis</artifactId>
<exclusions>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring-boot</artifactId>
</dependency>
Key bean to declare
#Bean(name="mybatis")
public MyBatisComponent myBatisComponent( SqlSessionFactory sqlSessionFactory )
{
MyBatisComponent result = new MyBatisComponent();
result.setSqlSessionFactory( sqlSessionFactory );
return result;
}
I'm trying to use Swagger to document my Rest API. I want to make use of #BeanParam annotation, however Swagger interprets the bean model as a single body. I've changed my swagger dependency to swagger-jersey2-jaxrs_2.10 but that made Wildfly unable to start cause of WELD-001408 error (as in first link below). I have read a lot of stuff, but nothing seems to solve my problem:
https://developer.jboss.org/thread/240847
https://github.com/swagger-api/swagger-core/issues/446
https://groups.google.com/forum/#!msg/swagger-swaggersocket/K5TFkxIcRQs/A34nupqPTTcJ
I've tried by changing dependencies in my pom.xml according to linked threads, now it looks like this:
<dependency>
<groupId>com.wordnik</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.3.12</version>
</dependency>
<dependency>
<groupId>com.wordnik</groupId>
<artifactId>swagger-core_2.10</artifactId>
<version>1.3.12</version>
</dependency>
<dependency>
<groupId>com.wordnik</groupId>
<artifactId>swagger-jersey2-jaxrs_2.10</artifactId>
<version>1.3.12</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers.glassfish</groupId>
<artifactId>jersey-gf-cdi</artifactId>
<version>2.14</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.14</version>
</dependency>
Moreover, I have a custom servlet for Swagger:
public class SwaggerServlet extends HttpServlet {
private static final long serialVersionUID = 4104485315753399385L;
#Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
BeanConfig beanConfig = new BeanConfig();
beanConfig.setVersion("1.0.2");
beanConfig.setBasePath("/CityAlertsWeb/service");
beanConfig.setResourcePackage("pl.cityalerts.web.controllers");
beanConfig.setScan(true);
ClassReaders.setReader(new JerseyApiReader());
}
}
Is there any way to make #BeanParam work in Swagger with Resteasy?
Should I add any other dependency?
With such a config I'm getting:
...
Caused by: java.lang.RuntimeException: Unable to instantiate ContextResolver
at org.jboss.resteasy.spi.ResteasyProviderFactory.registerProvider(ResteasyProviderFactory.java:1607)
at org.jboss.resteasy.spi.ResteasyProviderFactory.registerProvider(ResteasyProviderFactory.java:1310)
at org.jboss.resteasy.spi.ResteasyProviderFactory.registerProvider(ResteasyProviderFactory.java:1232)
at org.jboss.resteasy.spi.ResteasyDeployment.registerProvider(ResteasyDeployment.java:531)
at org.jboss.resteasy.spi.ResteasyDeployment.registration(ResteasyDeployment.java:338)
at org.jboss.resteasy.spi.ResteasyDeployment.start(ResteasyDeployment.java:241)
at org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap.contextInitialized(ResteasyBootstrap.java:28)
at io.undertow.servlet.core.ApplicationListeners.contextInitialized(ApplicationListeners.java:173)
at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:187)
... 7 more
Caused by: java.lang.IllegalArgumentException: Unable to find a public constructor for provider class org.glassfish.jersey.media.multipart.MultiPartProperties$Feature$MultiPartContextResolver
at org.jboss.resteasy.spi.ResteasyProviderFactory.createConstructorInjector(ResteasyProviderFactory.java:2184)
at org.jboss.resteasy.spi.ResteasyProviderFactory.createProviderInstance(ResteasyProviderFactory.java:2173)
at org.jboss.resteasy.spi.ResteasyProviderFactory.addContextResolver(ResteasyProviderFactory.java:1072)
at org.jboss.resteasy.spi.ResteasyProviderFactory.registerProvider(ResteasyProviderFactory.java:1601)
... 15 more
Thanks
Even though RESTEasy 3.X has been officially released about a year and a half ago, it is still fairly uncommon, at least in our experience.
Swagger-core comes in several flavors, as a Play module, Servlet, and JAX-RS. When it comes to JAX-RS, there's a basic JAX-RS implementation for JAX-RS 1.X and then there are specific implementations for Jersey 1.X and Jersey 2.X.
The Jersey 1.X and 2.X implementations include support for file uploads in those libraries as, unfortunately, file uploads are not part of the JAX-RS specification and end up being implementation-specific.
However, another difference in the Jersey 2.X specific implementation is the support for JAX-RS 2.0, which includes the #BeanParam support. At the moment, there is no general-purpose JAX-RS 2.0 module.
From the original link, it seems there's a conflict between JBoss/WildFly and loading the Jersey dependencies, which the Jersey 2.X flavor pulls in. Based on the interactions in the comments, the solution is to exclude (<exclusion>) the org.glassfish.jersey.media:jersey-media-multipart dependency (which is indeed the one for file upload support) and adding it again manually in the main pom.xml. While not an elegant solution, it works as a workaround.
I would also suggest opening an issue about it in the swagger-core repository. I imagine JAX-RS 2.0 adoption will grow over time and we should give it proper support.
I am using Spring MVC to create a RESTful service, using the #Controller and #RequestMapping annotations to control responses. I am also using Maven as a dependency management system.
In one function, I use a URI template in my #RequestMapping to retrieve a variable from the GET request. This function returns JSON when it is complete.
Due to problems with the JSTL libraries as a result of using URI templates (essentially I was getting 500 status codes because of a ClassNotFoundException with a JSTL class), I had to add the following dependencies to my Maven POM file (these come from our private repository, but you should be able to understand what they are):
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2-rev-1</version>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
<version>2.2</version>
</dependency>
However, as a result of adding these, I now get 404 errors, because Tomcat (which is handling the requests under Spring) is trying to resolve my URI, which is usually
localhost:9095/DiagnosticToolService/demo-object/1/json (the 1 being my GET variable, of course)
to a file, specifically
localhost:9095/DiagnosticToolService/WEB-INF/jsp/demo-object/1/json.jsp
Of course, this file does not exist. How do I turn off this automatic JSP resolution in Tomcat so that it can work properly? Also, are those the dependencies I needed to add to fix the 500 error? The 500 error and the 404 error are shown below:
The 500 error
The 404 error
Are you using #ResponseBody on your controller method that produces JSON? from the description of the problem it looks like the request is not making it to your controller or the return value from the controller is interpreted as a view name.
Can you post the mapping you are using on the controller just the method signature?