How to init Weld 3.0 cid setParameterName on Tomcat 8.5/Servlet 3.1 - cdi

I'm trying to upgrade an old web app from JSF 2.1.1-FCS to 2.2.14 running in the Tomcat 8.5 Servlet 3.1 container.
The Mojarra JSF minimum requirements (for the latest version I guess, the page doesn't seem clear) says among other things that CDI 1.2 is required with 2.0 recommended.
I added cd-api-2.0 and weld-servlet-shaded-3.0.0.Final along with the other dependencies. Things seem to work until I test some URLs we've been using a long time. Our application has been using a cid parameter. Weld uses the same parameter to track conversations. As a result we get the WELD-000321: No conversation found to restore for id error.
I would like to call the org.jboss.weld.context.http.HttpConversationContext.setParameterName(String cid) as early as possible to modify the value for this web application.
What is the best way to change this value in a Servlet 3.1 Container Context like the one provided by Tomcat 8.5?

Initialize WELD_CONTEXT_ID_KEY in web.xml
Using the web.xml context-param WELD_CONTEXT_ID_KEY allowed me to override the Weld CDI conversation parameter key name from cid to a value of my choosing so I could preserve the legacy usage of cid in my upgraded application and avoid the WELD-000321 error.
<context-param>
<param-name>WELD_CONTEXT_ID_KEY</param-name>
<param-value>customValue</param-value>
</context-param>
This was the simplest solution, but I didn't make the association between that context parameter name and the conversation parameter key or error WELD-000321 when first reading the Weld documentation.
Or set programmatically
I was also able to override the parameter name / context id key programmatically from a custom ServletContextListener.contextInitialized method based on the SO example for getting rid of the NonexistentConversationException. Since I'm on Tomcat 8.5 (Servlet 3.1) I was able to use either #WebListener or the listener element in web.xml. It didn't seem to matter if my web.xml web-app version was the old 2.5 or if I updated it to 3.1.
package ssce;
import java.util.UUID;
import javax.inject.Inject;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import org.jboss.weld.context.http.HttpConversationContext;
#WebListener
public class MyServletContextListener implements ServletContextListener {
#Inject
private HttpConversationContext conversationContext;
#Override
public void contextInitialized(ServletContextEvent sce) {
hideConversationScope();
}
#Override
public void contextDestroyed(ServletContextEvent sce) {
}
/**
* "Hide" conversation scope by replacing its default "cid" parameter name
* by something unpredictable.
*/
private void hideConversationScope() {
conversationContext.setParameterName(UUID.randomUUID().toString());
}
}

Related

Spring Boot 2.0: how to disable security for a particular endpoint

I need to completely bypass security (authentication / authorization) for certain endpoints in my spring boot 2.0 app--endpoints like "/version" and "/robots.txt"--but keep security in place for all other endpoints.
To complicate matters, I'm working in a project that's a part of a much larger project. My company has another group that has supplied a library that makes use of spring security. This is only relevant because it means I cannot simply override a spring security class to make this work--those classes have already been overridden with code I don't control.
Is there a way to configure spring boot 2.0 to bypass authentication for certain endpoints?
In sprint boot 1.5, we could specify this in our application.yml file:
security.ignored: /version
but in spring boot 2.0 this no longer works.
Federico's answer is correct. I added the following class to my Spring Boot 2.0 class:
package com.example.demo;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#Configuration
public class DemoConfigurer extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception{
http.authorizeRequests().antMatchers("/version").permitAll();
super.configure(http);
}
}
}

Java SE: #Inject does not work in Bean Validation validators called by RESTEasy

The following code from Hibernate Validator Reference Guide does not work in Java SE when RESTEasy is calling the validation:
public class ValidLicensePlateValidator implements ConstraintValidator<ValidLicensePlate, String> {
#Inject
private VehicleRegistry vehicleRegistry;
//rest of the class
The field vehicleRegistry is never injected.
Note that I have hibernate-validator-cdi.jar on the classpath.
Any idea what could be wrong with my setup? Or is this a bug in RESTEasy?
Here are (possibly misleading) outcomes of my investigation:
During application start RESTEasy shows the info log:
RESTEASY008550: Unable to find CDI supporting ValidatorFactory. Using default ValidatorFactory
From RESTEasy source code it seems that CDI enabled ValidationFactory is being looked up in AbstractValidatorContextResolver calling context.lookup("java:comp/ValidatorFactory") but it fails and non-CDI enabled ValidationFactory is used instead.

Weblogic Authenticate.authenticate equivalent in JBOSS 7

What is the equivalent code in JBOSS 7 for Weblogic's login security module code Authenticate.authenticate()
I recommend you toroughfully read JBOSS excellent migration guide .
WebLogic provides a proprietary ServletAuthentication class to perform programmatic login. In JBoss AS 7, you can use the standard Java EE6 Servlet 3.0 HttpServletRequest.login() method to perform programmatic login or you can define a element in the web.xml file.
To enable programmatic login, you must replace the WebLogic proprietary code with one of the following:
You can add the following annotations to the Servlet class that performs the authentication.
// Imports for annotations
import javax.annotation.security.DeclareRoles;
import javax.servlet.annotation.WebServlet;
import javax.servlet.annotation.HttpConstraint;
import javax.servlet.annotation.ServletSecurity;
#WebServlet("/securedUrlPattern")
#ServletSecurity(#HttpConstraint(rolesAllowed = { "myRole" }))
#DeclareRoles("myRole")
public class SecuredServlet extends HttpServlet {
//Rest of code
}
If you prefer not to use the standard servlet, you can instead add a element containing a dummy URL pattern to the web.xml file. This notifies JBoss to create a default Authenticator. Failure to create a element in the web.xml file may result in the error message "No authenticator available for programmatic login".
Another reason we should choose JBOSS over Weblogic

How can I initialize a Java FacesServlet

I need to run some code when the FacesServlet starts, but as FacesServlet is declared final I can not extend it and overwrite the init() method.
In particular, I want to write some data to the database during development and testing, after hibernate has dropped and created the datamodel.
Is there a way to configure Faces to run some method, e.g. in faces-config.xml?
Or is it best to create a singleton bean that does the initialization?
Use an eagerly initialized application scoped managed bean.
#ManagedBean(eager=true)
#ApplicationScoped
public class App {
#PostConstruct
public void startup() {
// ...
}
#PreDestroy
public void shutdown() {
// ...
}
}
(class and method names actually doesn't matter, it's free to your choice, it's all about the annotations)
This is guaranteed to be constructed after the startup of the FacesServlet, so the FacesContext will be available whenever necessary. This in contrary to the ServletContextListener as suggested by the other answer.
You could implement your own ServletContextListener that gets notified when the web application is started. Since it's a container managed you could inject resources there are do whatever you want to do. The other option is to create a #Singleton ejb with #Startup and do the work in it's #PostCreate method. Usually the ServletContextListener works fine, however if you have more than one web application inside an ear and they all share the same persistence context you may consider using a #Singleton bean.
Hey you may want to use some aspects here. Just set it to run before
void init(ServletConfig servletConfig)
//Acquire the factory instances we will
//this is from here
Maybe this will help you.

liferay redeploy: root context is null on redeploy

I have a web application with few spring portlets. Every portlet has an xml with its declared controller, but the services used by the controllers are placed in applicationContext.xml. I know that for every portlet is created one spring application context (from own xml file), and every that context has as root context the spring application context created from applicationContext.xml. That is all beans declared in applicationContext.xml are common for all portlets.
So let's have an example:
xml file for portlet example-portlet.xml:
...
...
controller ExampleController.java:
package example.controller;
#Controller
#RequestMapping(value = "VIEW")
public class NavigareController {
#Autowired
private ExampleService es;
...
}
applicationContext.xml:
...
<context:component-scan base-package="example.service />
...
service ExampleServiceImpl.java:
package example.service;
#Service
public class ExampleServiceImpl implements ExampleService {
...
}
When server starts with the application inside it, the application starts and everything works fine. When the application is redeployed then I have an error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'exampleController'...
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private example.service.ExampleService...
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [example.service.ExampleService]...
In result the portlet is not starting.
I have debugged the lifery's sources and I have found the following code:
package org.springframework.web.portlet
...
public abstract class FrameworkPortlet extends GenericPortletBean
implements ApplicationListener<ContextRefreshedEvent> {
...
protected ApplicationContext initPortletApplicationContext() {
ApplicationContext parent = PortletApplicationContextUtils.getWebApplicationContext(getPortletContext());
ApplicationContext pac = createPortletApplicationContext(parent);
...
The code above, in first case (when server starts with application inside) returns not null parent, but in second case (when application is redeployed) it retuns a null parent. Inside PortletApplicationContextUtils.getWebApplicationContext(getPortletContext()) there is the following code:
Object attr = pc.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
So in first case this attribute is in portlet context, but in the second case it is not in portlet context. The problem is clear, the exampleService bean is not found in null parent.
The question is: Is there any bug in hot deployment process?. Please help me!!!
What is your version of Liferay? If it is 6.1.1 then this is a known issue
http://issues.liferay.com/browse/LPS-29103
If you just need to deploy the portlets once - change order of listeners in web.xml manually as suggested in the ticket.
If you need to redeploy the portlets alot (for development) then the previous solution is very time consuming and the easiest way is to backport the fix from 6.2.0 branch.

Resources