I have a filter which maps just before the Faces Servlet and populate some Attributes in the HttpSession before it proceeds with the request
if (_clientUser != null && !_clientUser.isEmpty()) {
session.setAttribute(CLIENT_USER_URI_PARAM_NAME, _clientUser);
filterChain.doFilter(servletRequest, servletResponse);
return;
}
Within the URI there are some informations for which Task-flow should be addressed
faces/adf.task-flow?adf.tfId=task-flow-definition-id&adf.tfDoc=/WEB-INF/task-flow-definition-id.xml
After I proceed the request there is a method-call within the bounded task flow which is called before the view (lets call the view MainPage), by making it default activity
<default-activity>doStuff</default-activity>
The Method itself is within a PageFlowScoped Managed Bean, which is added to the task-flow-definition-id.xml
Here is the doStuff Method which is called before the "MainPage"-View
public class Controller{
public void doStuff {
FacesContext ctx = FacesContext.getCurrentInstance();
Map sessionMap = ctx.getExternalContext().getSessionMap();
String clientUser = (String) sessionMap.get(CLIENT_USER_URI_PARAM_NAME);
AppModImpl am = getApplicationModule();
DBTransaction transaction = am.getDBTransaction();
//do more stuff
}
}
public AppModImpl getApplicationModule() {
FacesContext fc = FacesContext.getCurrentInstance();
Application app = fc.getApplication();
ExpressionFactory elFactory = app.getExpressionFactory();
ELContext elContext = fc.getELContext();
ValueExpression valueExp =
elFactory.createValueExpression(elContext, "#{data.AppModDataControl.dataProvider}", Object.class);
AppModImpl am = (AppModImpl) valueExp.getValue(elContext);
return am;
}
Everything works fine till here. But if I try to get the Application Module. There is non.
This application normally doesn't have any DataControl, because is just a root Application which holds different components which have been added by ADFLibrarys, but I added an DataControl to the DataBindings.cpx and a iterator to the MainPagePageDef (just to include a DataControl in the bindings) but still no result.
Do you have any advice for me how I can access the Application Module? FacesServlet should have been already created the necessary FacesContext by the time the Managed Bean is called or does it only create a new FacesContext the Time an actual Page (jspx/jsf) loads?
I've found myself an answer:
Here is the Block Post which helped me figure it out.
http://andrejusb.blogspot.de/2012/02/how-to-fix-data-control-initialization.html
Related
i am currently writing Junit-Tests for on OData-Application (a hobby project). In there, I initialize a Servlet with the init() function. In order to receive specific application settings, i use the context.getResource() method.
Here is my code:
#Override
public void init(ServletConfig config) {
try {
super.init(config);
ServletContext context = getServletContext();
URL resourceUrl = context.getResource("/WEB-INF/config.properties");
if (resourceUrl == null) {
throw new ConfigurationException("Unable to find config.properties");
}
Path configFile = Paths.get(resourceUrl.toURI());
Now, I try to mock it. The Servlet itself is easy to mock, but im getting error when i try to mock the "getResource"-functionality. Here is my Junit-(beforeClass) Block:
public static ODataServlet getServlet() throws MalformedURLException {
if (servlet == null) {
servletConfig = new MockServletConfig();
MockServletContext context = new MockServletContext();
Path path = Paths.get("src/test/resources/config.properties");
when(context.getResource("/WEB-INF/config.properties")).thenReturn(path.toUri().toURL());
servlet = new ODataServlet(){
/**
*
*/
private static final long serialVersionUID = 1L;
public ServletContext getServletContext() {
return context; // return the mock
}
};
servlet.init(servletConfig);
}
return servlet;
}
Unfortunately, i always get the Exception:
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
In the line
when(context.getResource("/WEB-INF/config.properties")).thenReturn(path.toUri().toURL());
I dont understand why. the context-Object is a MockedObject (MockServletContext).
Any advice ? Im also thinking changing everytghing to classloader.getResource as a workaround. But actually i like it like this ...
Any help would be much appreciated.
Sephir
UPDATE: SOLVED. After literally only a few minutes in here, some guys pointed out the Issue: MockServletContext context is from the Package org.springframework.mock.web which is not working with the Mockito.
After changing the MockServletContext
MockServletContext context = new MockServletContext();
to
context = Mockito.mock(ServletContext.class);
everything is working.
Big thanks to you Guys (!).
I'm working on a solution in Adobe Experience Manager (AEM) that receives an HTTP request containing a URL to a file, which I want to download and store in the JCR.
So, I have a servlet that receives the request. It spawns a thread so that I can do the download in the background, and then redirects to a confirmation page. This allows me to send the user on their way without waiting while I try to download the file.
I can download the file just fine, but I'm having trouble getting a usable ResourceResolver to store the file in the JCR from my thread.
At first, I simply referenced the request's ResourceResolver in the background thread:
Servlet:
public void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response)
throws ServletException, IOException {
...
signingProvider.getDocFromService(params, request.getResourceResolver());
response.sendRedirect(confirmationPage);
}
And in the provider class:
public void getDocFromService(Map<String, String> params, ResourceResolver resolver) {
new Thread( new Runnable() {
public void run() {
Session session = null;
if (resolver != null) {
session = resolver.adaptTo(Session.class);
Node root = session.getRootNode();
...
}
}
}
}
but that didn't work. After reading up on resolvers vs threads, I thought I would be better off creating a new Resolver instance, so I tried to inject a ResourceResolverFactory:
Servlet:
signingProvider.getDocFromService(params);
Provider:
public void getDocFromService(Map<String, String> params) {
new Thread( new Runnable() {
#Reference
private ResourceResolverFactory resolverFactory;
// security hole, fix later
ResourceResolver resolver = resolverFactory.getAdministrativeResourceResolver(null);
Session session = null;
if (resolver != null) {
session = resolver.adaptTo(Session.class);
Node root = session.getRootNode();
...
}
}
}
but the ResourceResolverFactory is null, so I crash when asking it for a resolver. Apparently, no factory is getting injected into the #Reference
I would really rather not do the work on the main thread; after I download the file I'm going to turn around and read it from the JCR and copy it elsewhere. Both of these operations could be slow or fail. I have a copy of the file at the original URL, so the end-user needn't care if my download/uploads had trouble. I just want to send them a confirmation so they can get on with business.
Any advice on how to get a ResourceResolver in a separate thread?
For things like post\background processing you can use Sling Jobs. Please refer to the documentation to find out some details.
Note: #daniil-stelmakh brings a good point in his answer, sling jobs are much better suited for your purpose, to add to his answer, here is a sling tutorial that demonstrates sling jobs: https://sling.apache.org/documentation/tutorials-how-tos/how-to-manage-events-in-sling.html
To answer your question directly:
The issue, really is the placement of #Reference annotation.
That annotation is handled by Maven SCR Plugin and it should be placed on a private member of a '#Component' annotated class.
Basically move your ResourceResolverFactory declaration to become a private member of your class, not the Thread.
#Component(
label = "sample service",
description = "sample service"
)
#Service
public class ServiceImpl {
#Reference
private ResourceResolverFactory resolverFactory;
public void getDocFromService(Map<String, String> params) {
new Thread( new Runnable() {
// security hole, fix later
ResourceResolver resolver = resolverFactory.getAdministrativeResourceResolver(null);
Session session = null;
if (resolver != null) {
session = resolver.adaptTo(Session.class);
Node root = session.getRootNode();
...
}
}
}
}
I created web-service,where i am getting url params , which i am setting it to Object.
after it when i want to set to facesContext it is giving me NULL.I got Suggestion to implement AbstractFacesServlet.java class in project but any idea how can ?
And this is what code i am using _
public class ReserRes extends ServerResource {
#Post("xml")
public void $post() throws Throwable {
...........
.....
FacesHelper.setValueBindingObject("SelectedOtaReservationBean",
reservationBean);
......
}
And setValueBindingObject(,,) is
public static final void setValueBindingObject(String expression,
final Object value) {
FacesContext facesContext = FacesContext.getCurrentInstance();
if (facesContext == null) // Always throwing NULL
throw new NullPointerException(
"Could not get a reference to the current Faces context");
Application application = facesContext.getApplication();
ValueBinding vb = application.createValueBinding(expression);
vb.setValue(facesContext, value);
}
In this i am not interacting with any .jsp or any kind of UI. i am getting params and binding with object. Is this wrong or any way to implement FacesContext for ws.?
I got one suggestion http://cwiki.apache.org/MYFACES/access-facescontext-from-servlet.html to use this class. any buddy know how can i implement or set object to FacesContext using this?
Thanx
In cases where the user has closed the browser and walked away, I want to log when the session times out. For example as a system induced log out as opposed to user request (I already have working and tested code to log a user requested logout).
Since the user isn't actively submitting requests (especially if it is just a matter of the now unused session timing out on the server) I don't think a filter is possible. Can this be done with a phase listener? If so can you provide some insight or a skeleton, or at least point me in the right direction on how this might be done.
My understanding is that the session on the server is still active until it times out or some other mechanism invalidates it. I am assuming therefore that a phase listener will also be able to tell if as part of your login method, you kill any existing session prior to the user logging in again with a fresh view, other machine, etc.
I am OK with research, but would like to at least start while pointed in the right direction. :)
On a second note: Is it possible to differentiate between a session time out and a view expired?
Thought I'd post the solution I ended up with based on the suggestions:
public class ElsSoulardSessionListener implements HttpSessionListener {
#EJB
private SessionLogger sessionLogger = new SessionLogger();
private SessionLogDTO sessionData = new SessionLogDTO();
private ElsDateTimeFunctions ts = new ElsDateTimeFunctions();
private static final Logger logger = Logger.getLogger(ElsSoulardSessionListener.class.getSimpleName());
#Override
public void sessionCreated(HttpSessionEvent se) {
// Nothing to do yet
}
#Override
public void sessionDestroyed(HttpSessionEvent se) {
logger.log(Level.FINE, "SESSION DESTROYED LISTENER");
HttpSession session = se.getSession();
finalizeUserSessionLog(session);
}
/**
* Utility method to finalize user's session log entry. Returns
* early if the session log isn't found or more than one is returned.
* #param session
*/
private void finalizeUserSessionLog(HttpSession session) {
String sessionId = session.getId();
LogoutReasonType logoutReason = (LogoutReasonType) session.getAttribute("logoutreason");
if (logoutReason == null) {
logoutReason = LogoutReasonType.SESSION_TIMEOUT;
}
try {
sessionData = sessionLogger.findBySessionId(sessionId);
} catch (NonexistentEntityException | UnexpectedResultSetSizeException ex) {
logger.log(Level.WARNING, " sessionDestroyed ", ex);
return;
}
Calendar now = ts.getUtcDateTimeAsCalendar();
sessionData.setLogoutTimestamp(now);
sessionData.setLogoutReason(logoutReason);
sessionLogger.update(sessionData);
}
}
If this helps you...
In our application we have extended HttpSessionListener and used sessionDestroyed method to log the event of session timeout.
and registered the same in web.xml as
<listener>
<listener-class>
com.ourpackage.OurHttpSessionListener
</listener-class>
</listener>
I believe which you only catch events of the servlet container through ServletFilters. PhaseListener only exist inside JSF "sessions", after servlet requests. Check the JSF life cycle to make sure. After, you can create another request for invalidate the "session" in JSF
I wanted to make a custom annotation to check security on some functions for my JSF web application. For security I use Tomcat security with JaaS, so I have no application managed security to my disposal.
What actually want to do is make an annotation for my methods in the Backing Beans like Spring Security (#Secured("role")). My security system is implemented so that every function is a role and you can dynamically make "user roles" these are stored in the DB and when somebody logs in all the (function)roles in that "user role" will be set in tomcat security as roles.
So now I have this piece of code to check if my user can access the function:
public static void checkSecurity(final String function) {
final FacesContext facesContext = FacesContext.getCurrentInstance();
try {
if (facesContext.getExternalContext().getRemoteUser() == null) {
facesContext.getExternalContext().redirect("login.xhtml");
return;
}
if (!facesContext.getExternalContext().isUserInRole(function)) {
facesContext.getExternalContext().redirect("restricted.xhtml");
return;
}
} catch (final Exception ex /* Mandatory "IOException e" will be caught + all other exceptions. */) {
facesContext.getExternalContext().setResponseStatus(403); // HTTP Status 403: Forbidden. Can also throw 401.
facesContext.responseComplete();
}
}
Now I have to call this SecurityUtil.checkSecurity("name_of_function"); in every method.
But I want to have an annotation like this #CustomSecurity("function_name_role").
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface CustomSecurity {
// Single Element called value.
String value();
}
And when a method has this annotation the checkSecurity function automatically has to be performed. So I have to scan for this annotation at a point, or make some kind of actionlistener. JSF should have some options for this but all the forums I found on this don't really help.
Does somebody has some ideas?
EDIT:
I tried this blog it works but only on an action of a component (and components don't render when you don't have the role). So how secure is this when people try to hack into the JSF structure. And I rather have it running on every method.
public class SecurityActionListener extends ActionListenerImpl implements ActionListener {
private static final Logger LOGGER = FacesLogger.APPLICATION.getLogger();
#SuppressWarnings("unused")
#Override
public void processAction(final ActionEvent event) {
final FacesContext context = FacesContext.getCurrentInstance();
final Application application = context.getApplication();
final ConfigurableNavigationHandler navHandler = (ConfigurableNavigationHandler) application.getNavigationHandler();
// Action stuff
final UIComponent source = event.getComponent();
final ActionSource actionSource = (ActionSource) source;
MethodBinding binding;
binding = actionSource.getAction();
final String expr = binding.getExpressionString();
if (!expr.startsWith("#")) {
super.processAction(event);
return;
}
final int idx = expr.indexOf('.');
final String target = expr.substring(0, idx).substring(2);
final String t = expr.substring(idx + 1);
final String method = t.substring(0, (t.length() - 1));
final MethodExpression expression = new MethodExpressionMethodBindingAdapter(binding);
final ELContext elContext = context.getELContext();
final ExpressionFactory factory = context.getApplication().getExpressionFactory();
final ValueExpression ve = factory.createValueExpression(elContext, "#{" + target + '}', Object.class);
final Object result = ve.getValue(elContext);
// Check if the target method is a secured method
// and check security accordingly
final Method[] methods = result.getClass().getMethods();
for (final Method meth : methods) {
if (meth.getName().equals(method)) {
if (meth.isAnnotationPresent(CustomSecurity.class)) {
final CustomSecurity securityAnnotation = meth.getAnnotation(CustomSecurity.class);
System.out.println("Function to check security on: " + securityAnnotation.value()); // TODO TO LOG
SecurityUtil.checkSecurity(securityAnnotation.value());
} else {
super.processAction(event);
}
break;
}
}
}
}
And this in the faces-config.xml:
<action-listener>
com.nielsr.randompackagebecauseofnda.SecurityActionListener
</action-listener>
This blog could also be an answer, but I don't know how it will work with my JaaS Tomcat security because the security is in a separate project deployed as a standalone JAR in the tomcat lib folder.
But I actually don't know that I have to secure my Beans. Because I have configured all the functions (aka roles see above) that are on 1 page in the Web.xml as security constraints. And I render the components on the page only if you have to rights or "function_role" on that component. So is this secured enough? Or if somebody has a right to a function on a page can he render the components himself and so hack my site?
I'm not that familiar to JSF to know this, what is going on in that extra JSF abstraction layer between Controller and View? (I'm more of a Spring MVC developer, but because of requirements I have to use JSF but it's nice to broaden my knowledge.)
You can "scan for your Annotations" using
http://code.google.com/p/reflections/
Regards