I am trying to fetch an article from the db using jquery code
this is the jquery function
function searchArticle(codeArticle){
if(codeArticle){
//alert(codeArticle);
var detailHtml ="";
$.getJSON("detailArticle",
{
codeArticle: codeArticle,
ajax:true
},
function(data){
if(data){
detailHtml+= "<tr>"+
"<td>"+data[0].article.codeArticle+"</td>"+
"<td>1</td>"+
"<td>"+data[0].prixUnitaireTTC+"</td>"+
"<td>0</td>"+
"</tr>";
$("#detailNouvelleCommande").append(detailHtml);
}else{
alert("article not found");
}
});
}
}
and this is my controller method
#RequestMapping(value = "/detailArticle")
#ResponseBody
public Article getArticleByCode(String codeArticle){
if(codeArticle == null){
return null;
}
Article article = articleService.findOne("codeArticle", codeArticle);
if(article == null){
return null;
}
return article;
}
the method selects the article from database correctly however while returning it I receive the following eror:
java.lang.IllegalArgumentException: No converter found for return value of type: class com.stock.mvc.entity.Article
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:187)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:174)
at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:81)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:132)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
Related
I need to add additional business-logic for POST method. For now, I'm going to reuse the logic from RepositoryEntityController for getting and save the needed object.
#RepositoryRestController
#RequestMapping("/customPost")
public class UserController implements ApplicationEventPublisherAware {
private final UserRepository userRepository;
private final RepositoryRestConfiguration config;
private final HttpHeadersPreparer headersPreparer;
private ApplicationEventPublisher publisher;
#Autowired
public UserController(UserRepository userRepository, RepositoryRestConfiguration config, HttpHeadersPreparer headersPreparer) {
this.userRepository = userRepository;
this.config = config;
this.headersPreparer = headersPreparer;
}
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
#ResponseBody
#RequestMapping(
value = {"/{repository}"},
method = {RequestMethod.POST}
)
public ResponseEntity<ResourceSupport> postCollectionResource(PersistentEntityResource payload, PersistentEntityResourceAssembler assembler, #RequestHeader(value = "Accept", required = false) String acceptHeader) throws HttpRequestMethodNotSupportedException {
return this.createAndReturn(payload.getContent(), assembler, this.config.returnBodyOnCreate(acceptHeader));
}
private ResponseEntity<ResourceSupport> createAndReturn(Object domainObject, PersistentEntityResourceAssembler assembler, boolean returnBody) {
publisher.publishEvent(new BeforeCreateEvent(domainObject));
Object savedObject = userRepository.save((User) domainObject);
publisher.publishEvent(new AfterCreateEvent(savedObject));
PersistentEntityResource resource = returnBody ? assembler.toFullResource(savedObject) : null;
HttpHeaders headers = headersPreparer.prepareHeaders(resource);
addLocationHeader(headers, assembler, savedObject);
return ControllerUtils.toResponseEntity(HttpStatus.CREATED, headers, resource);
}
private void addLocationHeader(HttpHeaders headers, PersistentEntityResourceAssembler assembler, Object source) {
String selfLink = assembler.getSelfLinkFor(source).getHref();
headers.setLocation((new UriTemplate(selfLink)).expand(new Object[0]));
}
}
The code which I sent - is working ok. But the issue is that I need to add some request mapping #RequestMapping("/customPost") to controller.
Without this mapping - method will not work. I tried to have the same controller but without "/customPost" mapping. I got this exception at start of applicaton:
caused by: java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'repositoryEntityController' method
public org.springframework.http.ResponseEntity<org.springframework.hateoas.ResourceSupport> org.springframework.data.rest.webmvc.RepositoryEntityController.postCollectionResource(org.springframework.data.rest.webmvc.RootResourceInformation,org.springframework.data.rest.webmvc.PersistentEntityResource,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler,java.lang.String) throws org.springframework.web.HttpRequestMethodNotSupportedException
to {[/{repository}],methods=[POST],produces=[application/hal+json || application/json]}: There is already 'userController' bean method
public org.springframework.http.ResponseEntity<org.springframework.hateoas.ResourceSupport> com.project.controller.UserController.postCollectionResource(org.springframework.data.rest.webmvc.PersistentEntityResource,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler,java.lang.String) throws org.springframework.web.HttpRequestMethodNotSupportedException mapped.
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry.assertUniqueMethodMapping(AbstractHandlerMethodMapping.java:576) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry.register(AbstractHandlerMethodMapping.java:540) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.registerHandlerMethod(AbstractHandlerMethodMapping.java:264) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
I also tried to remove "/customPost" mapping from controller and change mapping in metod to "/users". But for this case, I have this exception:
java.lang.NullPointerException: null
at org.springframework.data.rest.webmvc.config.RootResourceInformationHandlerMethodArgumentResolver.resolveArgument(RootResourceInformationHandlerMethodArgumentResolver.java:86) ~[spring-data-rest-webmvc-2.6.10.RELEASE.jar:na]
at org.springframework.data.rest.webmvc.config.PersistentEntityResourceHandlerMethodArgumentResolver.resolveArgument(PersistentEntityResourceHandlerMethodArgumentResolver.java:113) ~[spring-data-rest-webmvc-2.6.10.RELEASE.jar:na]
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:158) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:661) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.27.jar:8.5.27]
The question is: how can I have needed logic without adding "/customPost" mapping?
Spring Data REST emits its own events when working with entities:
BeforeCreateEvent
AfterCreateEvent
BeforeSaveEvent
AfterSaveEvent
BeforeLinkSaveEvent
AfterLinkSaveEvent
BeforeDeleteEvent
AfterDeleteEvent
You can listen to these events to add your additional business logic. For example, to perform something after the SDR creates a new User (with POST method) or saves (updates) the existent User (with PUT/PATCH methods), you can use such a handler:
#Component
#RepositoryEventHandler
public class UserEventHandler {
private final UserServie userServie;
public UserEventHandler(UserServie userServie) {
this.userServie = userServie;
}
#HandleAfterCreate
public void handleAfterCreateUser(User user) {
userService.afterCreate(user)
}
#HandleAfterSave
public void handleAfterSaveUser(User user) {
userService.afterSave(user)
}
}
P.S. If I'm not mistaken, SDR emits these events outside the current transactions, only before it is started or after it is committed. You need to take this into account when implementing your business logic...
In the following method there are two parameters childFile and file, I run this call through postman but it gives me 400 Bad Request error when I check the logs it says that parameter childFile is not present, I attach code, error and postman screenshot please tell me what is the issue
Controller
#Transactional
#RequestMapping(method = RequestMethod.POST, value = "api/addchild",produces="application/json")
public ResponseEntity<?> child(Authentication authentication,
#RequestParam(value="childFile") String childFile, #RequestParam(value="file") MultipartFile file) {
ObjectMapper mapper = new ObjectMapper();
Child child;
try {
child=mapper.readValue(childFile, Child.class);
Child createdChild=childRepo.save(child);
if(createdChild!=null)
{
childService.createChildPhoto(file, createdChild.getId());
}
return ResponseEntity.ok("child created");
} catch (IOException e1) {
e1.printStackTrace();
}
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Child can not be created , please check your headers and string body again.");
}
Logs
Content-Disposition: form-data; name] with value ["childFile"
{
"id": 0,
"firstName": "Abeer",
"lastName": "Hashmi",
"gender": "Male",
"dateOfBirth": "1999-02-11",
"detail": null,
"emergencyNumber": "03001111115",
"medicalCondition": false,
"medicalConditionDescription": null,
"enabled": true
}
------WebKitFormBoundary3t9AJTMgmU7MV4da
Content-Disposition: form-data; name="file"; filename="child3.jpg"
Content-Type: image/jpeg
[![org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter 'childFile' is not present
at org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.handleMissingValue(RequestParamMethodArgumentResolver.java:198) ~\[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE\]
at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:109) ~\[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE\]
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121) ~\[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE\]
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:158) \[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE\]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128) \[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE\]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) \[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE\]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) \[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE\]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) \[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE\]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) \[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE\]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) \[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE\]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) \[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE\]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) \[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE\]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) \[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE\]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:661) \[tomcat-embed-core-8.5.23.jar:8.5.23\]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) \[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE\]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) \[tomcat-embed-core-8.5.23.jar:8.5.23\]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) \[tomcat-embed-core-8.5.23.jar:8.5.23\]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) \[tomcat-embed-core-8.5.23.jar:8.5.23\]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) \[tomcat-embed-websocket-8.5.23.jar:8.5.23\]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) \[tomcat-embed-core-8.5.23.jar:8.5.23\]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) \[tomcat-embed-core-8.5.23.jar:8.5.23\]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317) \[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE\]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127) \[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE\]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) \[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE\]][1]][1]
So I found a solution to this problem..The issue was with postman when I remove content-type header it works fine,Postman insert header by itself
You are using form data with a simple request param, that's not how it works. If you are trying to send the json and file together, make sure "childFile"'s content type is "application/json" and receive it by request body with annotation #RequestPart, and mapping produces should be "multipart/form-data", then it will do the job.
i'm encountering an error while producing JSON from DAO, here is my code
Controller
#RequestMapping(value="/findAdpId/", method=RequestMethod.POST , consumes = "application/json", produces = "application/json")
public #ResponseBody AllCustomerHist findAdpId(#RequestBody AllCustomerHist customer){
String customerId = customer.getCustomerId();
String srctable = customer.getSrctable();
System.out.println("customer ID = "+customerId);
System.out.println("srctable = "+srctable);
List<AllCustomerHist> adpcust = allCustomerHistService.findAdpId(customerId, srctable);
return (AllCustomerHist) adpcust;
}
DAO Class
#SuppressWarnings("unchecked")
public List<AllCustomerHist> findAdpId(String customerId, String srctable) {
// TODO Auto-generated method stub
Criteria criteria = getSession().createCriteria(AllCustomerHist.class)
.setProjection(Projections.projectionList()
.add(Projections.property("adpId"), "adpId"))
.add(Restrictions.eq("customerId", customerId))
.add(Restrictions.eq("srctable", srctable));
return (List<AllCustomerHist>)criteria.list();
}
what i want is, when retrieving JSON like
{
"customerId":"11",
"srctable":"transaction"
}
my DAO class will produce
{
"adpId":["abcd123","defw123"]
}
this is the error log
Exception
org.springframework.web.util.NestedServletException: Request
processing failed; nested exception is java.lang.ClassCastException:
java.util.ArrayList cannot be cast to
com.astra.adp.model.AllCustomerHist
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
Root Cause
java.lang.ClassCastException: java.util.ArrayList cannot be cast to
com.astra.adp.model.AllCustomerHist
com.astra.adp.controller.CustomerController.findAdpId(CustomerController.java:73)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
Note The full stack trace of the root cause is available in the server
logs.
thank you for the helps!
Hi I am getting following error.
java.lang.IllegalArgumentException: Unknown parameter position: 1]
with root cause java.lang.IllegalArgumentException: Unknown parameter
position: 1 at
org.hibernate.query.internal.QueryParameterBindingsImpl.getBinding(QueryParameterBindingsImpl.java:240)
at
org.hibernate.query.internal.AbstractProducedQuery.setParameter(AbstractProducedQuery.java:503)
at
org.hibernate.query.internal.AbstractProducedQuery.setParameter(AbstractProducedQuery.java:104)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498) at
org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:372)
at com.sun.proxy.$Proxy63.setParameter(Unknown Source) at
edu.zipcloud.cloudstreetmarket.core.daos.HistoricalIndexRepositoryImpl.findLastHistoric(HistoricalIndexRepositoryImpl.java:37)
at
edu.zipcloud.cloudstreetmarket.core.daos.HistoricalIndexRepositoryImpl.findLastIntraDay(HistoricalIndexRepositoryImpl.java:31)
at
edu.zipcloud.cloudstreetmarket.core.services.MarketServiceImpl.getLastDayIndexActivity(MarketServiceImpl.java:41)
at
edu.zipcloud.cloudstreetmarket.portal.controllers.DefaultController.fallBack(DefaultController.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498) at
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
at
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
at
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
at
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
at
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
at
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
at
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
at
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) at
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
inside method findLastHistoric(HistoricalIndexRepositoryImpl.java:37)
class:
#Repository
public class HistoricalIndexRepositoryImpl implements HistoricalIndexRepository{
#PersistenceContext
private EntityManager em;
#Override
public Iterable<HistoricalIndex> findIntraDay(String code, Date of) {
TypedQuery<HistoricalIndex> sqlQuery = em.createQuery("from HistoricalIndex h where h.index.code = ? and h.fromDate >= ? and h.toDate <= ? ORDER BY h.toDate asc", HistoricalIndex.class);
sqlQuery.setParameter(1, code);
sqlQuery.setParameter(2, DateUtil.getStartOfDay(of));
sqlQuery.setParameter(3, DateUtil.getEndOfDay(of));
return sqlQuery.getResultList();
}
#Override
public Iterable<HistoricalIndex> findLastIntraDay(String code) {
return findIntraDay(code, findLastHistoric(code).getToDate());
}
#Override
public HistoricalIndex findLastHistoric(String code){
TypedQuery<HistoricalIndex> sqlQuery = em.createQuery("from HistoricalIndex h where h.index.code = ? ORDER BY h.toDate desc", HistoricalIndex.class);
sqlQuery.setParameter(1, code);
return sqlQuery.setMaxResults(1).getSingleResult();
}
}
Please help me to resolve this error. If you need other information, let me know.
Regards.
How about this?
TypedQuery<HistoricalIndex> sqlQuery = em.createQuery("from HistoricalIndex h where h.index.code = ?1 ORDER BY h.toDate desc", HistoricalIndex.class);
Check here section 5.3.2. Query creation
TL;DR:
Service method annotated with #Transactional(propagation = Propagation.NOT_SUPPORTED)
Hibernate 5.0.4.Final: everything works as expected (method is executed without transaction)
Hibernate 5.2.5.Final: javax.persistence.TransactionRequiredException: no transaction is in progress is thrown
as a testcase for this issue I created a simple maven web app and the only change made in code (copy-paste from old working project) was Hibernate version bump in pom.xml
Question:
What is the proper way to execute service methods without transaction nowadays?
Code snippets (Spring used as a main framework):
DAO:
#Repository
public class UrlDaoImpl implements UrlDao {
#Autowired
private SessionFactory sessionFactory;
#Override
public List<Url> getAllUrls() {
Session session = sessionFactory.getCurrentSession();
Query query = session.createQuery("from Url");
return query.list();
}
}
Service:
#Service
public class UrlServiceImpl implements UrlService {
#Autowired
private UrlDao urlDao;
#Override
#Transactional // THIS WORKS IN NEW HIBERNATE
public List<Url> getAllUrls() {
return urlDao.getAllUrls();
}
#Override
#Transactional(propagation = Propagation.NOT_SUPPORTED) // THIS USED TO WORK BUT NOW THROWS EXCEPTION
public List<Url> getAllUrlsNoTxn() {
return urlDao.getAllUrls();
}
}
Controller:
#Controller
public class HomeController {
#Autowired
private UrlService urlService;
#RequestMapping(value = "/", method = RequestMethod.GET, produces = "text/plain")
public String entryPoint() {
urlService.getAllUrls();
System.out.println("--------------------- ok");
return "ok";
}
#RequestMapping(value = "/no-txn", method = RequestMethod.GET, produces = "text/plain")
public String entryPointNoTxn() {
// EXCEPTION WILL BE THROWN BELOW
urlService.getAllUrlsNoTxn();
System.out.println("--------------------- ok no txn");
return "ok no txn";
}
}
Stacktrace for the exception in new Hibernate:
exception
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
root cause
javax.persistence.TransactionRequiredException: no transaction is in progress
org.hibernate.internal.SessionImpl.checkTransactionNeeded(SessionImpl.java:3439)
org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1410)
org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1406)
org.springframework.orm.hibernate5.SessionFactoryUtils.flush(SessionFactoryUtils.java:144)
org.springframework.orm.hibernate5.SpringSessionSynchronization.beforeCommit(SpringSessionSynchronization.java:95)
org.springframework.transaction.support.TransactionSynchronizationUtils.triggerBeforeCommit(TransactionSynchronizationUtils.java:95)
org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCommit(AbstractPlatformTransactionManager.java:932)
org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:744)
org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:504)
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:292)
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
com.sun.proxy.$Proxy32.getAllUrlsNT(Unknown Source)
com.example.web.controller.HomeController.entryPointNoTxn(HomeController.java:31)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:220)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:116)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
Ok, after few hours of trying different configurations (before posting this question to SO), I finally found the solution.
For new Hibernate versions there is another required parameter that must be declared on #Transactional if you want to execute a method without a transaction: readOnly = true. So the working example of the Service part is:
#Service
public class UrlServiceImpl implements UrlService {
#Autowired
private UrlDao urlDao;
#Override
#Transactional
public List<Url> getAllUrls() {
return urlDao.getAllUrls();
}
#Override
#Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED) // ADDED READONLY TO WORK IN NEW HIBERNATE VERSIONS
public List<Url> getAllUrlsNoTxn() {
return urlDao.getAllUrls();
}
}
I also confirmed that this works on debug by calling ((org.hibernate.engine.transaction.internal.TransactionImpl) session.getTransaction()).isActive(); which returns true for the first Service method (with transaction) and false for the second Service method (with Propagation.NOT_SUPPORTED).