I'm doing a login. The problem is: my isUserLoggedIn() method is called several times by other sessions (i've checked using
(HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false)).
The Login bean (of a JSF page) is this:
#Named
#SessionScoped
public class Login implements Serializable {
#Inject
private Credentials credentials;
private UserData user;
public String login() {
if (this.credentials.getUsername().equals("daniel")) {
user = new UserData("Daniel");
return "success";
}
return "failure";
}
public boolean isUserLoggedIn() {
return user != null;
}
public String logout() {
user = null;
((HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false)).invalidate();
return "success";
}
public String getUsername() {
return getUser() == null ? "" : getUser().getUsername();
}
#Produces
public UserData getUser() {
return user;
}
}
So, what happens is: when login() is called, I can see via getSession() that it is X, but then, afterwards while trying to access another page, when calling isUserLoggedIn(), the getSession() method returns Y instead of X, and the user attribute is null. Frequently the isUserLoggedIn() method is called several times with just 1 request, and it's session changes each time it is called.
By the way, I'm using JBoss AS7 Final, and my faces-config.xml is the following:
<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="2.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=" http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">
<navigation-rule>
<from-view-id>/login.xhtml</from-view-id>
<navigation-case>
<from-action>#{login.login}</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/secured/home.xhtml</to-view-id>
<redirect />
</navigation-case>
<navigation-case>
<from-action>#{login.login}</from-action>
<from-outcome>failure</from-outcome>
<to-view-id>/login.xhtml</to-view-id>
<redirect />
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/*.xhtml</from-view-id>
<navigation-case>
<from-action>#{login.logout}</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/login.xhtml</to-view-id>
<redirect />
</navigation-case>
</navigation-rule>
</faces-config>
Any ideas? Thank you.
After some time back there I discovered that the problem had to do with the url path. The cookie was generated for a path and when changing the path and trying to access the session, it was generated another one.
Anyway, I discovered that this is definitely NOT the way to secure Java EE apps (see Java EE 6 manual), so I'm going other way.
Thanks.
Related
I created one spring boot application. When I run this I am getting below error for persiatance.xml.
Seems like it is not reading my persistance.xml file. Could you please help me in resolving the issue.
Exception in thread "main" javax.persistence.PersistenceException: No Persistence provider for EntityManager named EmployeeData
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:61)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39)
at com.JPAproject.Entity.InsertEmployee.main(InsertEmployee.java:11)
Below are the related file for reference:
Entity class
package com.JPAproject.Entity;
import javax.persistence.Entity;
import javax.persistence.Table;
#Entity
#Table(name="Employee_JPA")
public class Employee_EntityManager {
private String e_id;
private String e_name;
private Integer e_age;
public String getE_id() {
return e_id;
}
public void setE_id(String e_id) {
this.e_id = e_id;
}
public String getE_name() {
return e_name;
}
public void setE_name(String e_name) {
this.e_name = e_name;
}
public Integer getE_age() {
return e_age;
}
public void setE_age(Integer e_age) {
this.e_age = e_age;
}
public Employee_EntityManager(String e_id, String e_name, Integer e_age) {
super();
this.e_id = e_id;
this.e_name = e_name;
this.e_age = e_age;
}
public Employee_EntityManager() {
super();
}
}
Persistance.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="EmployeeData" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.JPAproject.Employee_EntityManager</class>
</persistence-unit>
</persistence>
The org.hibernate.ejb.HibernatePersistence class has been deprecated for a long time, but you still find it in old tutorials. You need to use the new one org.hibernate.jpa.HibernatePersistenceProvider.
You also don't seem to have a data source, if that is your full XML file, and not a reduced version, so that you don't post passwords and such.
I start to learn Spring Cache abstraction.
I use Spring boot, Spring Data Jpa, EhCache provider for this purpose.
My ehcache.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ehcache>
<ehcache>
<diskStore path="java.io.tmpdir"/>
<defaultCache maxElementsInMemory="100"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true">
</defaultCache>
<cache name="teams"
maxElementsInMemory="500"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="100"
overflowToDisk="false">
</cache>
My service:
#CacheConfig(cacheNames = "teams")
#Service
public class TeamService {
#Autowired
private TeamRepository teamRepository;
#Cacheable
public Team findById(long id) {
return teamRepository.findById(id).get();
}
#Cacheable
public List<Team> findAll() {
return teamRepository.findAll();
}
#CachePut
public Team save(Team team) {
return teamRepository.save(team);
}
#CacheEvict
public void delete(long id) {
teamRepository.deleteById(id);
}
}
My controller:
#RestController
public class TeamController {
#Autowired
private TeamService teamService;
#GetMapping("/teams")
public List<Team> getAll() {
return teamService.findAll();
}
#GetMapping("/team/{id}")
public Team getById(#PathVariable long id) {
return teamService.findById(id);
}
#DeleteMapping("/team/{id}")
public void delete(#PathVariable long id) {
teamService.delete(id);
}
#PostMapping("/team")
public Team save(#RequestBody Team team) {
return teamService.save(team);
}
}
I am performing requests to my controller...
When I perform getAll() method of the controller data are cached correctly and then don't exucute query to database at next times. Then I update and delete data from the database using corresponding methods of my controller, which service methods are marked as #CachePut and #CacheEvict respectively and must refresh cache. Then I perform above getAll() method again and get the same response like at the first time but I want that it will be refreshed after performing delete and update requests.
What's I doing wrong or How I can get the desired result?.
When you put #Cachable annotation on a method so all entries will be kept on cache added by default a name then the first cachable is different to second cachable, so if you want to work well you need to add a name that you want, for example:
#Cachable("teams")
#Cachable("teams")
#CachePut("teams")
#CacheEvict(value="teams", allEntries=true)
You can get more information in this link: https://www.baeldung.com/spring-cache-tutorial
Perhaps a best solution would be this:
#Cachable("team")
#Cachable("teams")
#Caching(put = {
#CachePut(value="team"),
#CachePut(value="teams") })
#Caching(evict = {
#CacheEvict(value="team", allEntries=true),
#CacheEvict(value="teams", allEntries=true) })
i have this below code .
advice on setter is not triggered even though setter is called.
i can see it in the console
if i do advice on String getName() everything works just fine.
but its not working on setter public void setName(String name).
spring.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<aop:aspectj-autoproxy />
<bean id="cust" class="aspectJ.Customer">
<property name="name" value="logging" />
</bean>
<bean id="aspect" class="aspectJ.LoggingAspect"/>
</beans>
Logging ASPECT
#Aspect
public class LoggingAspect {
#Before("allgetters()")
public void printAspect() {
System.out.println("Aspect Running");
}
#Before("allgetters()")
public void printAspectTwo() {
System.out.println("Aspect TWO Running");
}
#Pointcut("execution(public void setName(*))")
public void allgetters() {
}
}
CUSTOMER CLASS
package aspectJ;
public class Customer {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
System.out.println("SETTER CALLED");
}
}
Main Class
public class MainClass {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
Customer obj = (Customer) context.getBean("cust");
}
}
Your aspect signature is wrong.
* will match a singular field
.. will match zero or multiple fields
Example 1
com.stackoverflow.*.Customer.setName(..)
Matches all packages starting with com.stackoverflow and ending with Customer. The wildcard will only match one package name. The method can accept zero or more arguments. Below are three examples of what it will match:
com.stackoverflow.question.Customer.setName()
com.stackoverflow.question.Customer.setName(String arg1)
com.stackoverflow.question.Customer.setName(String arg1, String arg2)
Example 2
com..Customer.setName(*, *)
Match all packages starting with com and ending with Customer. Accept methods with two arguments of any type. Below are two examples of what it will match. Notice that the wildcard will accept any number of packages.
com.example.Customer.setName(String arg1, Object arg2)
com.stackoverflow.question.Customer.setName(Integer arg1, Double arg2)
You should change your allgetters() to the following:
#Pointcut("execution(public void setName(..))")
public void allgetters() {
}
Spring AOP only works with beans managed by Spring. A bean is not managed until it is initialized, regardless if it is defined in Java or XML.
//The Customer object returned by this method is managed.
//The Customer object within the method is not managed
#Bean
public Customer createCustomer(){
//This is a pure Java object
Customer customer = new Customer();
//The object is not yet managed. This method call will therefore never be intercepted by your Pointcut.
customer.setName(“John Doe”);
return customer;
}
Quote from the documentation:
Spring AOP only supports method execution join points for Spring
beans, so you can think of a pointcut as matching the execution of
methods on Spring beans.
Just Posting what user #javamusings said :
The advice is called only when the setter is called in the Java class. It is not called when the property is initialized in the aspectj.xml
I am trying to implement ehcache to get static data (from table) loaded during application startup however when I make a call again to database, the call is going to database (can see running sql on console) instead of taking values from ehcache.
my code is:
ehcache.xml as below:
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd"
updateCheck="true"
monitoring="autodetect"
dynamicConfig="true">
<diskStore path="java.io.tmpdir" />
<cache name="ObjectList"
maxEntriesLocalHeap="10000"
maxEntriesLocalDisk="1000"
eternal="false"
diskSpoolBufferSizeMB="20"
timeToIdleSeconds="2000000" timeToLiveSeconds="900000000000"
memoryStoreEvictionPolicy="LFU"
transactionalMode="off">
<persistence strategy="localTempSwap" />
</cache>
</ehcache>
my repository class is:
public interface customRepository extends JpaRepository<Object, Long> {
#Cacheable(value = "ObjectList", cacheManager="abclCacheManager")
public Object findById(Long id);
#Cacheable(value = "ObjectList", cacheManager="abclCacheManager")
public List<Object> findAll();
}
and my cacheInitialiser class is:
#Configuration
#EnableCaching
#ComponentScan("com.abcl.process")
public class EhCacheConfiguration {
#Bean("abclCacheManager")
public CacheManager cacheManager() {
return new EhCacheCacheManager(ehCacheCacheManager().getObject());
}
#Bean
public EhCacheManagerFactoryBean ehCacheCacheManager() {
EhCacheManagerFactoryBean cmfb = new EhCacheManagerFactoryBean();
cmfb.setConfigLocation(new ClassPathResource("ehcache.xml"));
cmfb.setShared(true);
cmfb.setCacheManagerName("abclCacheManager");
return cmfb;
}
}
I am testing my this using below:
public class testCache {
doSomething() {
List<Object> listObject = repo.findAll();
listObject.size();
}
public void getOne() {
Object o = repo.findById(1L);
}
}
I can see a db hit in getAll method however I thought the results would get stored in cache and in the second call there would not be a db hit by method getById however I see a db hit on second call as well.
Can anyone please suggest if I am missing anything here.
When you cache the results of findAll it creates a single entry in the cache which maps the key generated by Spring caching, since your method has no parameter, to the List<Object>. It does not put into the cache one mapping per list element between id and the Object.
So when you use findById(Long), Spring caching will look for a cache entry mapping to the id. And since it cannot find one, it will hit the database.
There is no way of having Spring caching put one mapping per collection element. If that is really what you need, you will have to code it instead of relying on the #Cacheable annotation.
I'm basing my knowledge on how to do this on this Crunchify tutorial.
I have a single page application.
It has two functions. It needs to either send a request to the HTTP servlet, which will go call its own java, and from which it will recieve a JSON string containing any errors/advising the servlet what to do next.
The other function is that it prompts a save file dialog from the servlet.
The question is - how can I structure my servlet such that it returns a plain text HTTP response for the AJAX query to examine.
I have a very round about way of doing this, and I'd like a suggestion for how to achieve the same thing in a simpler manner.
web.xml
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/submitQuery</url-pattern>
<url-pattern>/saveFile
</servlet-mapping>
MyServlet-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="world.hello.myservlets" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
MyServlet.java
package world.hello.myservlets;
#Controller
public class MyServlet{
#RequestMapping("/submitQuery")
public ModelAndView submitQuery()
{
return new ModelAndView("text", "model", "hello world");
}
}
/WEB-INF/jsp/text.jsp
{model}
index.html
<html>
<head>
<script>
function myAjax()
{
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
alert(xmlhttp.responseText)
/*do something with the http response*/
}
}
xmlhttp=new XMLHttpRequest();
xmlhttp.open("GET", "submitQuery", true);
xml.send();
}
</script>
</head>
<body>
<button onclick="myAjax()">Click me</button>
</body>
</html>
My understanding is the way this works is when the /submitQuery URI is sent, it's mapped to the MyServlet servlet. The servlet then returns a ModelAndView of ViewName = text, ModelName = model.
The dispatcher then redirects to /jsp/text.jsp (the specified view), displays the model on it. That final rendered output is returned to the AJAX object which can then access it how it wants.
Is there a more straight forward way of doing this?
Yes there is more straight way for doing this.
As per crunchify tutorial you are returning the ModelAndView object. So that's the reason you are getting model object on text.jsp
ModelAndView: It returning both model and view information from a controller. Holder for both Model and View in the web MVC framework. Note that these are entirely distinct. This class merely holds both to make it possible for a controller to return both model and view in a single return value.
More about ModelAndView
Now come to the other way in which you need to return plain text.
Annotate your submitQuery() method in controller with #ResponseBody annotation:
#RequestMapping(value="/submitQuery")
#ResponseBody
public String submitQuery() {
return "Response";
}
The #ResponseBody can be put on a method and indicates that the return
type should be written straight to the HTTP response body (and not
placed in a Model, or interpreted as a view name)
Access the parameter in javascript.
function myAjax()
{
xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
alert(xmlhttp.responseText);
console.log(xmlhttp.responseText);
}
}
xmlhttp.open("GET", "submitQuery", true);
xmlhttp.send();
}
There's a slightly more direct way of doing it, and it involves #ResponseBody. You can skip the jsp rendering by doing this:
#RequestMapping(value = "/somestring", method = RequestMethod.GET)
public #ResponseBody
String getSomeString() {
return "some string";
}
If you want to use something besides a string, you can. The object will get serialized to JSON. Example:
#RequestMapping(value = "/myobject", method = RequestMethod.GET)
public #ResponseBody
MyObject getSomeString() {
return new MyObject("blah");
}
Please find below some of the observations:
The MyServlet class which is annotated with #Controller is not a servlet. It takes care of the controller aspect of MVC design pattern.
The only servlet that is being used here is DispatcherServlet. It is a front facing servlet for all Spring MVC based appliations
I would suggest renaming the DispatcherServlet name, as MyServlet name gives a feeling that the servlet is handwritten
And NO, this is not a round about way of implementation. The steps that you have followed is the standard way of working with Spring MVC.
This blog post gives a sample Ajax implementation using Spring MVC:
http://www.mkyong.com/spring-mvc/spring-mvc-jquery-autocomplete-example/