In my controller, put a value from a MySQL
database into a ModelAndView object
There is a separate program that updates the table and the MVC is supposed to grab that value so there are no forms to update that table.
When the table is updated, and when I hit refresh on the browser, the values will not update on the page.
Controller
@SuppressWarnings("unchecked")
@Secured({ "ROLE_USER", "ROLE_ADMIN" })
@RequestMapping(value = { "/", "/welcome" }, method = RequestMethod.GET)
public ModelAndView defaultPage(@ModelAttribute("user") User user) {
Collection<SimpleGrantedAuthority> authorities = (Collection<SimpleGrantedAuthority>) SecurityContextHolder
.getContext().getAuthentication().getAuthorities();
ModelAndView view = new ModelAndView("/hello");
// Redirects to admin page if user has admin role
if (authorities.toString().contains("ROLE_ADMIN")) {
return new ModelAndView("redirect:/admin");
}
/////
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String userName = auth.getName();
User userInfo = userDAO.getUserInfo(userName);
System.out.println("Here's the thing " + userInfo.getLastname() + " " + userInfo.getUserDetails());
Details details = userDAO.getDetailsInfo(userInfo.getUserDetails().getLastname(),
userInfo.getUserDetails().getPostcode());
Plugs plugs = userDAO.getPlugInfo(details.getMacAddress());
String json = plugs.getJson();
JSONObject obj = new JSONObject(json); //this is the value that is not updating
String name = obj.getJSONObject("meta").getJSONObject("locate").getString("value");
System.out.println(name);
view.addObject("json", obj);
return view;
}
I know this is pretty looked down upon, but I putting that value in Javascript.
like this:
<c:set var="json" value="${json}"/>
var __data__ = ${json};
Why won't the MVC display the correct value when the database is updated?
I want it to update on refresh
EDIT: I've disabled caching and cleared cache still have a problem. Any help?
In this quick article, we explained how to debug 404 errors in Spring MVC. We went through the two most common reasons for receiving a 404 response from our Spring application. The first was using an incorrect URI while making the request. The second was mapping the DispatcherServlet to the wrong url-pattern in web.
The @RequestMapping annotation can be applied to class-level and/or method-level in a controller. The class-level annotation maps a specific request path or pattern onto a controller. You can then apply additional method-level annotations to make mappings more specific to handler methods.
Is Spring MVC still used? Yes. Whenever someone uses Spring Boot for creating RESTful web services, chances are they are using Spring MVC (part of Spring Web starter, see http://start.spring.io and search Web in dependencies) although Spring has also been offering another web framework, Spring WebFlux.
The controller returns an object of ModelAndView. The DispatcherServlet checks the entry of view resolver in the XML file and invokes the specified view component.
Definitely PersistenceContextType.EXTENDED
scope is the root cause for your problem as you identified. The reason below:
With PersistenceContextType.TRANSACTION
scope, Spring framework takes responsibility of managing the life cycle of the injected the entitymanager
. The life of TRANSACTION
scope is tied to the underlying transaction
and upon commit/rollback of the transaction the entityManager
is closed by the spring framework.
But with PersistenceContextType.EXTENDED
scope, Spring framework takes responsibility of only injecting the entitymanager
. The life cycle of EXTENDED
scoped entity manager is not tied to the user transaction
and it can span multiple transactions. It is up to the application/user to explicitly close the entityManager
once we are done with it. If not it will remain open forever (or till Spring container is closed).
I presume in your userDAO
you are not closing entityManager
explicitly. And also 'userDAO' could be a singleton. So the same entityManager
that got injected only once is being used across multiple calls (or http requests)
With this the entityManager' remains open forever and so when you try to access any object (User/Plugin/UserDetails) the
entityManager` checks its first level cache, it will check its first level cache which it finds in it (that got loaded for the first time) and returns this object form its first level cache (which is stale) instead of hitting the database for the data.
And obviously with TRANSACTION
scope the entityManager
is closed by the Spring framework whenever transaction is completed (or method exits). This results in creating an entityManager
for each request (in your case web request) hits the the database which has the updated data.
See if this link helps. http://forum.spring.io/forum/other-spring-related/ejb/18445-injection-of-persistencecontext-with-persistencecontexttype-extended
So the solution I have has nothing to do with the code I posted, but in my UserDAO.java class.
Simple change.
From this:
@PersistenceContext(type = PersistenceContextType.EXTENDED)
private EntityManager em;
To this:
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
private EntityManager em;
and it works. Thank for the people who commented and tried to help/
EDIT: I hate answering my own questions, so if someone could have an in depth explanation on why this works, I'll accept it as an answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With