Can't get SessionContext on EJB - ejb

I can't get a SessionContext object on an EJB. I've tried all the options suggested on 4 Ways to Get EJBContext in EJB 3 and none of them worked. For example, the following code in my project...
#Stateful
public class SecurityService {
#Resource
private SessionContext context;
#PostConstruct
public void init() {
}
}
... generates the following exception during deploy:
[#|2012-02-28T14:35:02.805-0300|SEVERE|glassfish3.1.1|javax.enterprise.system.core.com.sun.enterprise.v3.server|_ThreadID=18;_ThreadName=admin-thread-pool-4848(5);|The log message is null.
java.lang.NullPointerException
at com.sun.appserv.connectors.internal.api.AppSpecificConnectorClassLoaderUtil.detectResourceInRA(AppSpecificConnectorClassLoaderUtil.java:266)
at com.sun.appserv.connectors.internal.api.AppSpecificConnectorClassLoaderUtil.processDescriptorForRAReferences(AppSpecificConnectorClassLoaderUtil.java:211)
at com.sun.appserv.connectors.internal.api.AppSpecificConnectorClassLoaderUtil.processDescriptorForRAReferences(AppSpecificConnectorClassLoaderUtil.java:130)
at com.sun.appserv.connectors.internal.api.AppSpecificConnectorClassLoaderUtil.detectReferredRARs(AppSpecificConnectorClassLoaderUtil.java:118)
at com.sun.appserv.connectors.internal.api.ConnectorClassLoaderServiceImpl.getConnectorClassLoader(ConnectorClassLoaderServiceImpl.java:111)
at com.sun.enterprise.v3.server.ClassLoaderHierarchyImpl.getConnectorClassLoader(ClassLoaderHierarchyImpl.java:117)
If I remove the #Resource annotation it deploys, but does not work (i've tried with JNDI and the other methods cited before).
I'm using Glassfish 3.1.1, and my project is JSF with CDI and EJB locally to services with JPA. I've tried injecting SessionContext on CDI beans but received the same errors. My EJB are configured with annotations, and my beans.xml have no configurations (but exists).
One strange thing is that with JNDI lookup I've managed to get an object of type SessionContextImpl on path java:/comp/EJBContext on the #PostConstruct init() method. BUT, it goes to null as soon as another EJB method is called (?) and it does not contain user's roles data (a call to isCallerInRole() throws an exception). Also, it is not an EJBContext object.
I'm packaging everything in a WAR using Maven, and the dependency of Java EE is marked as provided, as the following shows:
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>6.0</version>
<scope>provided</scope>
</dependency>
It seems to me that there is no SessionContext (EJBCOntext) been provided by the container at all. I don't know even if that is possible, and I have no idea on how to solve this.
Please, If you have ANY idea about this, I'll be glad to hear it. Thank you.

If your Principal has logged in using j_security_check, you can inject the SecurityContext in an EJB, or in a ManagedBean, and retrieve Principal's and role's information like this:
#Context private SecurityContext context;
....
boolean isInRole = context.isUserInRole("A role");
Principal p = context.getUserPrincipal();

Well, I've upgraded to Glassfish 3.1.2 and the problem was solved. Now I can inject javax.ejb.SessionContext as expected.
Special thanks to #perissf for the help.

Related

TestRestTemplate and spring security

I am learning spring rest. I am slowly building an application. I had full integration testing working well using TestRestTemplate.
However, I just started adding spring security to my application. Literally as soon as I add the spring security dependency, my testing fails.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
I get these errors like so:
Error while extracting response for type [class [Lcom.myproject.model.viewobjects.AView;] and content type [application/json]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of `[Lcom.myproject.model.viewobjects.AView;` out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `[Lcom.myproject.model.viewobjects.AView;` out of START_OBJECT token
at [Source: (PushbackInputStream); line: 1, column: 1]
When I debug, the object it returns which it is trying deserialize is null. If I put a breakpoint on the rest controller it doesn't even get there.
It seems like just adding the dependency turns a lot of defaults on. How do I test with security on?
1)Can I disable the security for testing somehow?
2)Can I somehow allow no credentials or send acceptable fake credentials? (I did see examples of #WithMockUser but that doesn't work with TestRestTemplate)
Edit:
I tried adding a security implementation to my test class to enable anonymous access and permitall:
#EnableWebSecurity
class TestSecurityConfig extends WebSecurityConfigurerAdapter
{
#Override
protected void configure(HttpSecurity http) throws Exception
{
http.anonymous().and().authorizeRequests().antMatchers("/**").permitAll();
}
}
The result of this is that #GetMapping work. I can trace that the calls reach the controller. But #PostMapping still do not work. The calls never reach the controller.
The post calls look like so:
updatedAView = restTemplate.postForObject(create_aview_url, aView, AView.class);
Why would get work but not post???
Also, to make sure there wasn't something else, I again went and removed the spring-boot-starter-security dependency and all the code that relates. Suddenly everything works. So it is definitely the security config that does this.
If you include the spring-boot-starter-security dependency, spring security is enabled by default. TestRestTemplate requests will be processed through the security system.
If you want to test without authentication, you can configure a version of WebSecurityConfigurerAdapter with #EnableWebSecurity for testing only that is permissive. You may need to exclude other configurations so they don't override this.
Here is an example:
#EnableWebSecurity
class TestSecurityConfig extends WebSecurityConfigurerAdapter
{
#Override
protected void configure(HttpSecurity http) throws Exception
{
http.anonymous().and().csrf().disable().authorizeRequests().antMatchers("/**").permitAll();
}
}
This allows you to make requests without user credentials
http.anonymous()
If you don't include the:
csrf().disable()
#GetMapping will work but no PostMapping or requests that change data as that is when csrf comes into play and it is enabled by default.
This permits you to access all the URLs in your application. You can of course limit this if you like:
authorizeRequests().antMatchers("/**").permitAll()

ClassCastException when using Bean Validation with weld

I'm running an application in Tomcat using Weld (org.jboss.weld.servlet:weld-servlet:2.0.2.Final with maven) to produces ValidatorFactory and Validator components like this:
#Produces
#Default
#javax.enterprise.context.ApplicationScoped
public ValidatorFactory getInstance() {
return Validation.byDefaultProvider().configure().buildValidatorFactory();
}
And
#Produces #javax.enterprise.context.ApplicationScoped
public Validator getInstanceValidator() {
return factory.getValidator();
}
When I inject Validator and calls method Validator.forExecutables(), I'm getting this exception:
org.jboss.weld.proxies.Validator$1284425531$Proxy$_$$_WeldClientProxy
cannot be cast to javax.validation.executable
But if I inject ValidatorFactory and calls ValidatorFactory.getValidator().forExecutables(), all works fine.
There are wrong in my code? Or there are another procedure to avoid this error?
EDIT
Analyzing Hibernate validator source code, I see that ValidatorImpl implements both Validator and ExecutableValidator interface. When weld creates the proxy, it implements only methods found in Validator interface, and not ExecutableValidator methods.
There are way to resolve this?
Which version of Hibernate Validator is this?
Actually Hibernate Validator's CDI ValidatorBean returns ExecutableValidator as type as well, so the proxy should be created for this. I vaguely remember that we had issues with that in a Beta release, so it might be you're still using that one.

Write Junit tests for Spring MVC application which internally relies upon ContextLoader.getCurrentWebApplicationContext()

I'm trying to write integration tests for a controller in our spring mvc application. The controller invokes a service class which in turn invokes a dao to read/write data from the repository. The DAO needs to lookup some configuration. The configuration bean is defined in WEB-INF/applicationContext.xml.
I'm using something like this:
Configuration config =(Configuration)ContextLoader.getCurrentWebApplicationContext().getBean("config");
private String namespace = config.getProperty("someproperty");
The properties are stored in zookeeper so I'm not using spring's property management artifacts.
The problem is that while running the JUnit test ContextLoader.getCurrentWebApplicationContext() always returns null.
I have so far looked at the following approaches:
1. Ted Young's approach ( just google search for spring mvc integration tests ted young)
2. https://github.com/SpringSource/spring-test-mvc
3. this site.. questions/8464919/unit-testing-a-servlet-that-depends-on-springs-webapplicationcontextutils-getre
4. Use Selenium/JWebunit
5. http://confluence.highsource.org/display/Hifaces20/Hifaces20+Testing+package+-+testing%2C+tracing+and+debugging+web+applications+with+Jetty
1 doesn't resolve this issue. WebApplicationContext stays null
2 states that support for WebApplicationContext will be available in spring 3.2
3. I don't understand this. Where do I get the testApplicationContext and the getServletContext() from?
4. I do not want to go this way as this is completely blackbox testing.
5. I'm currently looking at 5. But this requires starting up a servlet container. Is there no other alternative?
I will appreciate any help you can provide.
Thanks
PixalSoft
#Ted Young SO didn't allow me to finish what I was saying.With loader=MockWebApplicationContextLoader,isn't it supposed to be available as the default contextloader exactly as the Spring ContextLoader behaves when the webapp is initialized by a servletcontainer?Is there something special I need to do get a handle on the MockWebApplicationContextLoader?Injecting the config object works for singleton objects. But all can't be singleton. Passing a config object in every constructor sounds too tedious. For now, I have created a class which has a static config object, autowired via a setter method. I will take a look at ApplicationContextAware.Many thx
You have to manually add the WebApplication context to ContextLoderListner.
This will work.
#ContextConfiguration(locations = "classpath:module-test-beans.xml")
#WebAppConfiguration
public class SampleTest extends AbstractTestNGSpringContextTests {
#Autowired
private WebApplicationContext wac;
#BeforeClass
public void setUp() throws ServletException {
MockServletContext sc = new MockServletContext("");
ServletContextListener listener = new ContextLoaderListener(wac);
ServletContextEvent event = new ServletContextEvent(sc);
listener.contextInitialized(event);
}
#Test
public void testMe() {
Assert.assertFalse(ContextLoader.getCurrentWebApplicationContext() == null);
}
}
Add the following code at the beginning of your junit test:
MockServletContext sc = new MockServletContext("");
sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
"/applicationContext-test.xml"); // <== Customize with your paths
ServletContextListener listener = new ContextLoaderListener();
ServletContextEvent event = new ServletContextEvent(sc);
listener.contextInitialized(event);
If you need to add more than one xml for the context path just put them in the same string separated with spaces, like this:
sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
"/applicationContext-test.xml /applicationContext-other.xml");
The reason why ContextLoader.getCurrentWebApplicationContext is returning null is because, when you use my MockWebApplicationContextLoader, you are neither using a web application context nor that particular ContextLoader implementation.
Since your repository is managed by Spring, why do not you simply inject the config object into the repository? Injecting the config object is the most appropriate way to get access to it. You can then initialize your namespace property in a method annotated with #PostConstruct.
Alternatively, your DOA could implement ApplicationContextAware to receive a copy of the application context during construction.
store your property file in your classpath.
now access that property in your controller class like this:
/*to access your filename.properties file */
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("filename.properties"));
String sServerLocation = properties.getProperty("key");
now you can access your property file.
I am sure it will work.

How do I get Web.xml context-param values in controller action method?

This feels like a basic question, but I haven't had much luck Googling.
My app connects to an SMTP server and sends mail through it. I need this SMTP server to be configurable based on which environment the app is deployed to.
How can I specify the specify the SMTP server name in my web.xml config file and access it from my Spring MVC 3.0 controller?
The controller does not extend or implement anything. It is completely annotation driven with #Controller and #RequestMapping. From what I have seen online, people access context-params via the servlet API. Being annotation driven, I do not have access to the servlet object.
I solved this.
Make your controller implement ServletContextAware, which requires a method called
setServletContext(ServletContext servletContext)
Spring MVC will inject the servlet context into this method if your controller is ServletContextAware.
Create a private variable on your controller to store the servletController that is injected into the above method. You can now use servletContext just as you would if you were using a regular servlet.
hth.
Adding an instance of Servletcontext and autowiring it worked for me
#Controller
public MyController {
// other instances relevant to your requirement
#Autowired
private ServletContext sCtx;
//other methods relevant to your requirement
}
I suppose following also should work:
void action(final HttpServletRequest request) {
final paramValue = request.getSession().getServletContext().getInitParameter("paramName");
...
}

How to obtain OSGi service references from a Servlet that is registered in OSGi HttpService?

It seems natural that a HttpServlet running in OSGi environment (i.e. registered in OSGi HttpService) would want to call some OSGi services to accomplish it's tasks. The question is how to obtain references to these OSGi service inside the servlet.
One way would be to inject dependencies into the HttpServlet instance that is being registered to the OSGi HttpService like this:
MyServlet servlet = new MyServlet();
servlet.setFooService(fooService);
httpService.registerServlet("/myservlet", servlet, initparams, context);
I'm not sure if this is a valid approach since in non-OSGi environment the servlet life-cycle is managed by the Web Container and hence the service reference would not be injected for the servlet instances created later on.
There is another way to solve this when using PAX Web as an implementation of the OSGi HttpService. PAX Web exports the OSGi BundleContext into the ServletContext as a special attribute "osgi-bundlecontext". The BundleContext can then be used to obtain necessary service references:
public void init(ServletConfig servletConfig) throws ServletException {
ServletContext context = servletConfig.getServletContext()
BundleContext bundleContext =
(BundleContext) context.getAttribute("osgi-bundlecontext");
ServiceReference serviceRef =
bundleContext.getServiceReference("com.foo.FooService")
}
However this approach is rather ugly and ties you to a concrete implementation of the OSGi HttpService. Do you know any other (and possibly better) solution to this problem?
If you use a setter for the dependency on the service, as you have shown, it can work outside of OSGi as well. You just need to use some other dependency injection mechanism. If there is none, you could provide a subclass that initializes the servlet using JNDI lookups or from the servlet context.
public class MyServlet_AdapterForMissingDI extends MyServlet{
public void init(ServletConfig config){
setFooService(getItFromSomewhere());
}
}
The point being that if you have DI capabilities that can inject setFooService, you can just use the same servlet in OSGi and elsewhere, if you do not (and still want to support this case), you provide an adapter.
On a related note, check out Felix SCR to configure your object's dependencies, and Pax Web Extender Whiteboard, which takes care of hooking your servlet up with the HttpService.
Specifically, without SCR and Whiteboard, you need to think about the case when the fooService becomes unavailable later, or the HttpService gets started after your servlet.
In these cases your servlet would have a reference to a dead service that prevents the bundle from being garbage-collected, or your servlet would not be registered with the HttpService.
Update: Here is the SCR descriptor I use for one of my servlets. SCR handles servlet instantiation, life-cycle, registration (via Whiteboard), and dependencies. There is no OSGi-specific code in the servlet. There is not even the need for a BundleActivator anymore (SCR registers all services):
<component name="oracle.statusServlet" >
<implementation class="mypackage.DataSourceStatusServlet"/>
<property name="service.description" value="Oracle DataSource status servlet" />
<property name="alias" value="/OracleDataSourceStatus" />
<property name="servlet-name" value="Oracle DataSource status servlet" />
<service>
<provide interface="javax.servlet.Servlet" />
</service>
<reference name="DATASOURCES"
interface="javax.sql.DataSource"
cardinality="0..n" policy="dynamic"
bind="bindDataSource" unbind="unbindDataSource"/>
</component>
The dependencies for the servlet are specified in the reference tag. SCR will do the service lookup and binding.
May be an old post and you already might have got the answer..
Are you launching felix or whatever OSGi container yourself. If that is the case you can set the bundle context as an attribute to the servlet context.
Whats wrong in using an http service by PAX. ultimately the thread management and other aspects are taken care of by the servlet container in which you run this http service.
You could inject the services into some object, which is then queried by the servlets.

Resources