Groovy: trouble printing out attributes from xml - groovy

I am trying to parse a xml file and print out attributes but it is not working.
Here is the Groovy code:
def Server1 = new XmlParser().parse('c:\\temp\\webSimplified.xml')
Server1.each {
println "Stuff in session-config: ${it}"
it.attributes().each {
println 'PLEASE PRINT OUT ATTRIBUTES: '
println it.toString()
}
}
Here is the webSimplified.xml
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>xpoweredBy</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
</web-app>
And here is the results from running my Groovy script: Nothing prints out from the 'it.attributes().each {' segment. How can I get that to work?
Stuff in session-config: {http://xmlns.jcp.org/xml/ns/javaee}servlet[attributes={}; value=[{http://xmlns.jcp.org/xml/ns/javaee}servlet-name[attributes={}; value=[jsp]], {http://xmlns.jcp.org/xml/ns/javaee}servlet-class[attributes={}; value=[org.apache.jasper.servlet.JspServlet]], {http://xmlns.jcp.org/xml/ns/javaee}init-param[attributes={}; value=[{http://xmlns.jcp.org/xml/ns/javaee}param-name[attributes={}; value=[fork]], {http://xmlns.jcp.org/xml/ns/javaee}param-value[attributes={}; value=[false]]]], {http://xmlns.jcp.org/xml/ns/javaee}init-param[attributes={}; value=[{http://xmlns.jcp.org/xml/ns/javaee}param-name[attributes={}; value=[xpoweredBy]], {http://xmlns.jcp.org/xml/ns/javaee}param-value[attributes={}; value=[false]]]], {http://xmlns.jcp.org/xml/ns/javaee}load-on-startup[attributes={}; value=[3]]]]
Stuff in session-config: {http://xmlns.jcp.org/xml/ns/javaee}session-config[attributes={}; value=[{http://xmlns.jcp.org/xml/ns/javaee}session-timeout[attributes={}; value=[30]]]]
Process finished with exit code 0

Of course nothing is printed. I taught you in the other answer how to print out attributes, butt you have no attributes, but child tags.
Try this:
def Server1 = new XmlParser().parse(/c:\temp\webSimplified.xml/)
Server1.each {
println "Stuff in ${it.name().localPart}: $it"
println()
it.children().each {
println 'PLEASE PRINT OUT child element: '
println it
println()
}
3.times { println() }
}

This works:
def Server1 = new XmlParser().parseText('''
<web-app
version="3.1">
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>xpoweredBy</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
</web-app>
''')
Output:
servlet-name : jsp
servlet-class : org.apache.jasper.servlet.JspServlet
init-param :
init-param :
load-on-startup : 3
session-timeout : 30

Assuming you want to print the sesssion config values (a qualified guess based on your question), the following would work:
def str = '''
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>xpoweredBy</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
</web-app>
'''
def xml = new XmlParser().parseText(str)
xml.'session-config'.'*'.each { node ->
println "${node.name().localPart} -> ${node.text()}"
}
note that node is an instance of groovy.util.Node and node.name() returns an instance of QName which is a namespace aware object. To get the 'local name' we call 'localPart' on the QName.
The gpath expression xml.'session-config'.'*'.each means:
from the root node (i.e. the xml variable here), select all child nodes with the name 'session-config' and then iterate over all child nodes under that node.
The above prints:
session-timeout -> 30

Related

FacesConverter is null (JSF 2.3, CDI 2.0)

I tried to setup a FacesConverter to display some entity through my JSF page as referenced in JSF specification.
I'm running the following:
- Open Liberty 19.0.0.11 (tested on 19.0.0.6 as well, don't ask me why this version, I picked randomly another one)
- Java Open JDK 13
- JSF 2.3
- CDI 2.0
I've added to my project the following web.xml:
<web-app id="WebApp_ID" version="4.0" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd">
<display-name>TestConverterInjection</display-name>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<enabled>true</enabled>
<async-supported>false</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>
*.xhtml</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
The following faces-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<faces-config
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_3.xsd"
version="2.3">
</faces-config>
The following beans.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
bean-discovery-mode="all"
version="2.0">
</beans>
I do have an AppConfig class, annotated with #FacesConfig(Version.JSF_2_3). All fine so far.
I've simple TestConverter annotated as such:
#FacesConverter(value = "testConverter", managed = true)
When looking through the BeanManager, my TestConverter seems to be available as it appears in the list.
My test.xhtml file looks like this:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:outputText value="#{testBean.selectedEntity.id}">
</h:outputText>
<br/>
<h:outputText value="#{testBean.selectedEntity}" converter="testConverter">
</h:outputText>
</html>
And my backing bean:
package com.test.beans;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.annotation.PostConstruct;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.util.AnnotationLiteral;
import javax.faces.view.ViewScoped;
import javax.inject.Inject;
import javax.inject.Named;
import com.test.entities.MyEntity;
#Named("testBean")
#ViewScoped
public class TestBean implements Serializable {
private List<MyEntity> listEntities;
private MyEntity selectedEntity;
#Inject private BeanManager beanManager;
#PostConstruct
public void init() {
this.listEntities = new ArrayList<MyEntity>();
for(int i = 0; i < 5; i++) {
this.listEntities.add(new MyEntity(i, "test_"+i, i+"_test"));
}
this.selectedEntity = this.listEntities.get(0);
Set<Bean<?>> beans = beanManager.getBeans(Object.class,new AnnotationLiteral<Any>() {});
for (Bean<?> bean : beans) {
System.out.println("bean: "+bean.getBeanClass().getName());
}
}
public List<MyEntity> getListEntities() {
return listEntities;
}
public void setListEntities(List<MyEntity> listEntities) {
this.listEntities = listEntities;
}
public MyEntity getSelectedEntity() {
return selectedEntity;
}
public void setSelectedEntity(MyEntity selectedEntity) {
this.selectedEntity = selectedEntity;
}
}
Should be all good right ? Well, at least it worked with Apache TomEE 8.0.0 PluME. But here on Open Liberty, I'm getting:
SRVE0777E: Exception émise par la classe d'application 'javax.faces.webapp.FacesServlet.service:236'
javax.servlet.ServletException:
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:236)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1255)
at [internal classes]
Caused by: java.lang.NullPointerException:
at org.apache.myfaces.cdi.converter.FacesConverterCDIWrapper.getAsString(FacesConverterCDIWrapper.java:62)
... 1 more
So, it looks like my bean is instantiated but is null... Features of Open Liberty are javaee8-0 (to be sure there wasn't anything missing). In the example above, if I'm removing the "managed = true" in my converter, it works. Some bug within CDI ?
I investigated the issue and I found that it's caused by beanManager.getBeans call. The bean is registered in the beanManger (as you demonstrated), but it's just not retrieved properly. Since the Converter uses generics, you need to search by type instead of class. I opened an issue in the MyFaces community and provided a patch! :)
https://issues.apache.org/jira/browse/MYFACES-4311
The fix will be included in MyFaces 2.3.7.
Thanks for spotting this one!

Exception handling with JSF in web.xml

The problem is that I don't completely understand what exceptions are handled and what aren't.
I created new com.me.exceptions.InvalidPasswordException and populated it in the web.xml along with other exceptions:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" 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-app_3_0.xsd">
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>/view/login.xhtml</welcome-file>
</welcome-file-list>
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/view/login.xhtml?faces-redirect=true</location>
<error-page>
<exception-type>com.me.exceptions.InvalidPasswordException</exception-type>
<location>/view/loginWrongPass.xhtml?faces-redirect=true</location>
</error-page>
<error-page>
<exception-type>java.io.IOException</exception-type>
<location>/view/404.xhtml?faces-redirect=true</location>
</error-page>
<filter>
<filter-name>AuthFulter</filter-name>
<filter-class>com.me.beans.AuthFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AuthFulter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
I throw it from the my LoginBean:
#ManagedBean(name = "loginBean")
#SessionScoped
public class LoginBean implements Serializable {
private static final long serialVersionUID = 1L;
private String userName;
private String password;
!!!getters and setters are omitted
public String login() throws InvalidPasswordException, IOException {
int result = UserDao.login(userName, password);
if (result == 0) {
System.out.println("home");
return "home";
}
else if (result == 1) {
throw new InvalidPasswordException();
}
}
}
Why my InvalidPasswordException is not handled? Also if I throw IOException from the same place, it also doesn't work, though IOException is handled if it is thrown in the case of wrong URI in the request.
Though I can see stack traces of both in the logs.
Also I tried to throw exceptions from filters, it also works fine.
in general throw InvalidPasswordException or InvalidUsernameException is not good practice. User pass credentials if you find user from db you will do login, if not return null and redirect to another page or the same page show message "user not found" . You are not compare password for throw exception!.
The first your method must be change to
public String login(){
UserObject resultObject = UserDao.login(userName, password);
if (resultObject == null) {
System.out.println("user not found ");
return "home";
}
if (resultObject != null) {
System.out.println("user in database ");
System.out.println("create user profile context " +resultObject.getEmail() + " saving user object to session);
return "userProfilePage";
}
return null;
}
After changing logic you can throw exception if you need instead of returning/redirecting , but throw / catch is not best practice "
"Do NOT throw exceptions if you can avoid it, it makes your code MUCH slower ".

How to upload files without turning it to temporary file? (NetBeans JSF Primefaces)

Good day to all!
I've been making a simple web Application using Netbeans, JSF and Primefaces that can upload .csv, .jpeg/.jpg and .pdf files. I made 2 folders which was stored in drive C: (uploaded folder and tmp folder).
I assigned the "uploaded" folder to where the uploaded files are stored and the "tmp" for the .tmp of the uploaded files. I've been through many question threads and video tutorial which I followed correctly.
I also downloaded the commons fileupload and commons io and added it to the library. It is working fine, it displays that it is uploading and even saw the .tmp file on the folder i assigned it to.
But I cannot see the uploaded files on my "uploaded" folder.
So, my question is,
How can I upload these files into my "uploaded" folder.
Here are my codes:
index.xhtml
<?xml version='1.0' encoding='UTF-8' ?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form enctype="multipart/form-data" >
<p:fileUpload fileUploadListener="#{FileUploadControl.fileUploadControl}"
mode="advanced"
update="messages"
auto="true"
sizeLimit="10000000"
allowTypes="/(\.|\/)(gif|jpe?g|csv|pdf)$/"
/>
<!-- -->
<p:growl id="messages" showDetail="true"/>
</h:form>
</h:body>
</html>
FileUploadControl.java
package controller;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import org.primefaces.model.UploadedFile;
#ManagedBean
#SessionScoped
public class FileUploadControl implements Serializable {
private String destination = "C:\\uploaded\\";
private UploadedFile file;
public UploadedFile getFile() {
return file;
}
public void setFile(UploadedFile file) {
this.file = file;
}
public FileUploadControl() {
}
public void TransferFile(String fileName, InputStream in) {
try {
OutputStream out = new FileOutputStream(new File(destination + fileName));
int reader = 0;
byte[] bytes = new byte[(int) getFile().getSize()];
while ((reader = in.read(bytes)) != -1) {
out.write(bytes, 0, reader);
}
in.close();
out.flush();
out.close();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
public void upload() {
String extValidate;
if (getFile() != null) {
String ext = getFile().getFileName();
if (ext != null) {
extValidate = ext.substring(ext.indexOf(".")+1);
} else {
extValidate = "null";
if (extValidate.equals("pdf")) {
try {
TransferFile(getFile().getFileName(), getFile().getInputstream());
} catch (IOException ex) {
Logger.getLogger(FileUploadControl.class.getName()).log(Level.SEVERE, null, ex);
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage("Wrong", "Error Uploading file..."));
}
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage("Succesful", getFile().getFileName() + "is uploaded."));
} else {
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage("Wrong_ext", "only extension .pdf"));
}
}
} else {
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage("Wrong", "Select File!"));
}
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" 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-app_3_0.xsd">
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<!--File upload commons -->
<filter>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
<init-param>
<param-name>thresholdSize</param-name>
<param-value>51200</param-value>
</init-param>
<init-param>
<param-name>uploadDirectory</param-name>
<param-value>C:\tmp</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
<!--File upload commons -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>faces/index.xhtml</welcome-file>
</welcome-file-list>
Thank you for your response and help. looking forward to it!
The main reason it's failing as at now is that you haven't bound the value attribute to your backing bean variable, so getFile() will always return null and upload will do nothing.
You're still probably not going to get any results because it appears that you're trying to combine two different modes of operation of the <p:fileUpload/> component.
Simple mode
You don't define a fileUploadListener
You define a value attribute on the component and bind to the UploadedFile type attribute in your backing bean (which you have)
Advanced mode
You don't define a value attribute
You define a fileUploadListener which is bound to a method in your backing bean (which you also have)

Wro4j Custom XML Model Location

I've put wro.xml in src/main/resources as there are some other resources and it's easier to access them in unit tests.
I need to extend some wro classes now to be able to read the model from another place, but can't get it working.
Necessary code
web.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>WebResourceOptimizer</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetBeanName</param-name>
<param-value>wroFilter</param-value>
</init-param>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>WebResourceOptimizer</filter-name>
<url-pattern>/resources/*</url-pattern>
</filter-mapping>
applicationContext.xml:
<bean id="wroFilter" class="ro.isdc.wro.http.ConfigurableWroFilter">
<property name="properties" ref="wroProperties" />
</bean>
<bean id="wroProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="classpath:wro.properties" />
</bean>
wro.properties:
managerFactoryClassName=com.example.web.wro.manager.factory.MyWroManagerFactory;
preProcessors=cssUrlRewriting,cssImport,semicolonAppender,lessCss
postProcessors=cssMin,jsMin
debug=true
MyWroManagerFactory:
public class MyWroManagerFactory extends CopyrightKeeperConfigurableWroManagerFactory {
private static final Logger LOG = LoggerFactory.getLogger(MyWroManagerFactory.class);
#Override
protected WroModelFactory newModelFactory() {
LOG.debug("Load wro.xml directly from classpath");
return new XmlModelFactory() {
#Override
protected InputStream getModelResourceAsStream() throws IOException {
final String resourceLocation = getDefaultModelFilename();
final InputStream stream = getClass().getResourceAsStream(resourceLocation);
if (stream == null) {
throw new IOException("Invalid resource requested: " + resourceLocation);
}
return stream;
}
};
}
}
CopyrightKeeperConfigurableWroManagerFactory:
public class CopyrightKeeperConfigurableWroManagerFactory extends ConfigurableWroManagerFactory {
private static final Logger LOG = LoggerFactory.getLogger(CopyrightKeeperConfigurableWroManagerFactory.class);
private static final String[] PROCESSORS = {
CssImportPreProcessor.ALIAS,
JawrCssMinifierProcessor.ALIAS,
CssMinProcessor.ALIAS,
JSMinProcessor.ALIAS
};
#Override
protected void contributePreProcessors(final Map<String, ResourcePreProcessor> map) {
for (String processor : PROCESSORS) {
if (map.containsKey(processor)) {
LOG.debug("Apply CopyrightKeeperProcessorDecorator on " + processor);
map.put(processor, CopyrightKeeperProcessorDecorator.decorate(map.get(processor)));
}
}
}
}
Why it can't find classes/wro.xml / How to use a custom location for wro.xml?
EDIT
Here's the full log output: http://pastebin.com/NeNy1NH4
The problem is that you are loading the model relative to the MyWroManagerFactory class:
final InputStream stream = getClass().getResourceAsStream(resourceLocation);
That means that it will look for the model in the folder where the class is located. Since your wro.xml is located in classes folder (which is a root for classpath), you should use the following:
ClassLoader.getSystemResourceAsStream(resourceLocation);
Alternatively you could use ClasspathUriLocator:
new ClasspathUriLocator().locate("classpath:" + resourceLocation)
EDITED:
Apparently this example discovered a problem which is described in the following issue:
Until the fix is ready, the following options are available:
Option 1
Option 2

Struts 2 + Waffle: User principal is always null

I am working on a Web application based on Java, JSP, Struts 2 and Waffle for security. I run it in Tomcat 6. My problem is that I cannot get a principal object in my ActionSupport class. To be more specific,
principalProxy.getUserPrincipal()
always returns null. When I put this in a .jsp file, however:
request.getUserPrincipal()
this does not return null. So the information must be available in the original HttpServletRequest object. Of course, I have tried calling getUserPrincipal() on the HttpServletRequest object in the ActionSupport class, but this also returns null.
My ActionSupport class is defined as
public class SomeAction extends ActionSupport
implements ServletRequestAware, ServletResponseAware, PrincipalAware {
...
Furthermore, my struts.xml defines an action with the servlet-config interceptor set, so the setPrincipalProxy() method does actually get called (verified by print statements). This is my struts.xml (shortened):
<package name="default" namespace="/" extends="struts-default">
<action name="some" class="com.my.package.SomeAction">
<interceptor-ref name="servlet-config" />
<interceptor-ref name="params">
<param name="excludeParams ">(.*)</param>
</interceptor-ref>
<interceptor-ref name="i18n"/>
<result name="success">/someresult.jsp</result>
</action>
</package>
The web.xml defines a security filter and a filter mapping that should match any URL. Here are the relevant parts:
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter>
<filter-name>SecurityFilter</filter-name>
<filter-class>waffle.servlet.NegotiateSecurityFilter</filter-class>
<init-param>
<param-name>principalFormat</param-name>
<param-value>fqn</param-value>
</init-param>
<init-param>
<param-name>roleFormat</param-name>
<param-value>both</param-value>
</init-param>
<init-param>
<param-name>allowGuestLogin</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>securityFilterProviders</param-name>
<param-value>
waffle.servlet.spi.BasicSecurityFilterProvider
waffle.servlet.spi.NegotiateSecurityFilterProvider
</param-value>
</init-param>
<init-param>
<param-name>waffle.servlet.spi.NegotiateSecurityFilterProvider/protocols</param-name>
<param-value>
Negotiate
NTLM
</param-value>
</init-param>
<init-param>
<param-name>waffle.servlet.spi.BasicSecurityFilterProvider/realm</param-name>
<param-value>WaffleFilterDemo</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>SecurityFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
When requesting SomeAction, I am prompted with a HTTP Basic Authentication dialog as desired. This shows that the SecurityFilter does in fact get applied, doesn't it? The setPrincipalProxy() method gets called as well. I can get a Principal object in the JSP page. So why is the Principal object always null when I try to access it in SomeAction?
One more thing, I am employing URL rewriting, in case that could have anything to do with it.
EDIT:
In response to batbaatar's request, the setting of the request in Java. Could not be much simpler.
#Override
public void setServletRequest(HttpServletRequest request) {
httpRequest = request;
}
The instance variable httpRequest is of type HttpServletRequest.
I still could not get a user principal object from the HTTPServletRequest. However, I am able to get a principal object from the Session:
private String getLoggedInUser() {
if (httpSession.containsKey(WAFFLE_PRINCIPAL_KEY)) {
WindowsPrincipal principal =
(WindowsPrincipal) httpSession.get(WAFFLE_PRINCIPAL_KEY);
return principal == null ? "" : principal.getName();
} else {
return "";
}
}
The session key is defined as:
private static final String WAFFLE_PRINCIPAL_KEY =
"waffle.servlet.NegotiateSecurityFilter.PRINCIPAL";
Still curious for an answer to the original question, though.

Resources