As the title states, I'm trying to use Whiteboard to host my VaadinServlet. After many failed attempts at using other embedded servlet containers such as Jetty and Grizzly, I came across this solution here, written by the Bndtools man himself, Peter. I've tried implementing this myself, but I'm getting an error I cannot solve myself:
[test.client.ui.ClientUI$ClientServlet(4)] Error during instantiation of the implementation object
java.lang.InstantiationException: test.client.ui.ClientUI$ClientServlet: test.client.ui.ClientUI$ClientServlet.<init>()
Caused by: org.apache.felix.log.LogException: java.lang.InstantiationException: test.client.ui.ClientUI$ClientServlet
at java.lang.Class.newInstance(Class.java:427)
at org.apache.felix.scr.impl.manager.SingleComponentManager.createImplementationObject(SingleComponentManager.java:253)
at org.apache.felix.scr.impl.manager.SingleComponentManager.createComponent(SingleComponentManager.java:127)
at org.apache.felix.scr.impl.manager.SingleComponentManager.getService(SingleComponentManager.java:871)
at org.apache.felix.scr.impl.manager.SingleComponentManager.getServiceInternal(SingleComponentManager.java:838)
at org.apache.felix.scr.impl.manager.AbstractComponentManager.activateInternal(AbstractComponentManager.java:850)
at org.apache.felix.scr.impl.manager.AbstractComponentManager.enable(AbstractComponentManager.java:419)
at org.apache.felix.scr.impl.config.ConfigurableComponentHolder.enableComponents(ConfigurableComponentHolder.java:376)
at org.apache.felix.scr.impl.BundleComponentActivator.initialize(BundleComponentActivator.java:172)
at org.apache.felix.scr.impl.BundleComponentActivator.<init>(BundleComponentActivator.java:120)
at org.apache.felix.scr.impl.Activator.loadComponents(Activator.java:258)
at org.apache.felix.scr.impl.Activator.access$000(Activator.java:45)
at org.apache.felix.scr.impl.Activator$ScrExtension.start(Activator.java:185)
at org.apache.felix.utils.extender.AbstractExtender.createExtension(AbstractExtender.java:259)
at org.apache.felix.utils.extender.AbstractExtender.modifiedBundle(AbstractExtender.java:232)
... 17 more
Caused by: java.lang.NoSuchMethodException: test.client.ui.ClientUI$ClientServlet.<init>()
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.newInstance(Class.java:412)
at org.apache.felix.scr.impl.manager.SingleComponentManager.createImplementationObject(SingleComponentManager.java:253)
at org.apache.felix.scr.impl.manager.SingleComponentManager.createComponent(SingleComponentManager.java:127)
at org.apache.felix.scr.impl.manager.SingleComponentManager.getService(SingleComponentManager.java:871)
at org.apache.felix.scr.impl.manager.SingleComponentManager.getServiceInternal(SingleComponentManager.java:838)
at org.apache.felix.scr.impl.manager.AbstractComponentManager.activateInternal(AbstractComponentManager.java:850)
at org.apache.felix.scr.impl.manager.AbstractComponentManager.enable(AbstractComponentManager.java:419)
at org.apache.felix.scr.impl.config.ConfigurableComponentHolder.enableComponents(ConfigurableComponentHolder.java:376)
at org.apache.felix.scr.impl.BundleComponentActivator.initialize(BundleComponentActivator.java:172)
at org.apache.felix.scr.impl.BundleComponentActivator.<init>(BundleComponentActivator.java:120)
at org.apache.felix.scr.impl.Activator.loadComponents(Activator.java:258)
at org.apache.felix.scr.impl.Activator.access$000(Activator.java:45)
at org.apache.felix.scr.impl.Activator$ScrExtension.start(Activator.java:185)
at org.apache.felix.utils.extender.AbstractExtender.createExtension(AbstractExtender.java:259)
... 18 more
I added empty constructors just for the hell of it to see if they changed anything but nope.
ClientUI and ClientServlet classes:
public class ClientUI extends UI
{
public ClientUI()
{
//Empty constructor.
}
#Override
public void init(VaadinRequest request)
{
//Typical UI initialization.
}
}
#VaadinServletConfiguration(productionMode = false, ui = ClientUI.class)
#Component(provide = Servlet.class, properties = {"alias=/test"}, immediate = true)
public class ClientServlet extends VaadinServlet
{
// Empty class. This class uses the annotations for servlet configuration instead of a web.xml.
public ClientServlet()
{
// Empty constructor.
}
}
Any idea on how to stop this error and get the servlet up and running?
Edit: New error! Steffen, who commented below, pointed out I may have needed to move the servlet class to a top-level class, in which I most likely did need to, but now I get this:
org.osgi.framework.ServiceException: Service cannot be cast: javax.servlet.Servlet
Caused by: org.apache.felix.log.LogException: org.osgi.framework.ServiceException: Service cannot be cast: javax.servlet.Servlet
at org.apache.felix.framework.ServiceRegistrationImpl.getFactoryUnchecked(ServiceRegistrationImpl.java:344)
at org.apache.felix.framework.ServiceRegistrationImpl.getService(ServiceRegistrationImpl.java:231)
at org.apache.felix.framework.ServiceRegistry.getService(ServiceRegistry.java:327)
at org.apache.felix.framework.Felix.getService(Felix.java:3574)
at org.apache.felix.framework.BundleContextImpl.getService(BundleContextImpl.java:468)
at org.osgi.util.tracker.ServiceTracker.addingService(ServiceTracker.java:411)
at org.apache.felix.http.whiteboard.internal.tracker.AbstractTracker.addingService(AbstractTracker.java:35)
at org.osgi.util.tracker.ServiceTracker$Tracked.customizerAdding(ServiceTracker.java:932)
at org.osgi.util.tracker.ServiceTracker$Tracked.customizerAdding(ServiceTracker.java:864)
at org.osgi.util.tracker.AbstractTracked.trackAdding(AbstractTracked.java:256)
at org.osgi.util.tracker.AbstractTracked.track(AbstractTracked.java:229)
at org.osgi.util.tracker.ServiceTracker$Tracked.serviceChanged(ServiceTracker.java:894)
at org.apache.felix.framework.util.EventDispatcher.invokeServiceListenerCallback(EventDispatcher.java:943)
at org.apache.felix.framework.util.EventDispatcher.fireEventImmediately(EventDispatcher.java:794)
at org.apache.felix.framework.util.EventDispatcher.fireServiceEvent(EventDispatcher.java:544)
... 12 more
Also, this question may eventually be deleted. I'm looking at this Vaadin/OSGi EnRoute example that does what I need and I have confirmed that it works. I may just use the example provider and API for an application or create something similar. I will leave this question up for now just to provide to the knowledge of the internet and see if anyone can answer!
Related
Suppose I have an abstract class called AbstractTestWithNetwork:
#RunWith(JUnit4.class)
public abstract class AbstractTestWithNetwork {
#ClassRule
public static Network network = Network.newNetwork();
#ClassRule
public static GenericContainer etcd = new GenericContainer<>("alpine:3.6")
.withNetwork(network);
}
I would like to simply re-use it to have the same container in several classes by extending it:
public class FirstTestClass extends AbstractTestWithNetwork {
#Test
public void emptyMethod() throws Exception {
System.out.println("An empty test method");
}
}
There is also a SecondTestClass with the same content.
I can run each class separately from IDE and they will pass. But when I run gradle test or choose the whole package with test classes from IDE, only the 1st test class passes. For the second I get:
org.testcontainers.containers.ContainerLaunchException: Container startup failed
Caused by:
org.rnorth.ducttape.RetryCountExceededException: Retry limit hit with exception
Caused by:
org.testcontainers.containers.ContainerLaunchException: Could not create/start container
Caused by:
java.lang.reflect.UndeclaredThrowableException
Caused by:
java.lang.reflect.InvocationTargetException
Caused by:com.github.dockerjava.api.exception.NotFoundException: {"message":"No such network: a48cf082ab42a55c843e9963c3938f44dd93cceae09e1724d4fefd5b45f235f1"}
I checked the implementation and spotted a bug in Networks' implementation.
In TestContainers <= 1.4.2, an instance of Network is not reusable, i.e. can't be used with #ClassRule.
But I have good news for you - there is a simple workaround until it's fixed: just remove #ClassRule from "network" field.
I am currently trying to use the ViewAccessControl Interface of vaadin.spring as explained in the last paragraph of this tutorial.
But when implementing the isAccessGranted Method I get the following error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'frontPageView': Scope 'vaadin-view' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No active view
The declaration of the FrontPageView class (The only thing I do in the enter method, is to add some vaadin ui elements):
#SpringView(name = FrontPageView.NAME)
public class FrontPageView extends DashboardDesign implements View, ViewAccessControl {
#Override
public void enter(ViewChangeEvent event) {
}
}
And my implementation of the isAccessGranted Method:
#Override
public boolean isAccessGranted(UI ui, String beanName) {
return SecurityContextHolder.getContext().getAuthentication().isAuthenticated();
}
P.S. Its basically the same problem this guy had a year ago: How to create a secure view with Vaadin and SpringViewProvider
Ok I figured it out now. If anyone else ever finds this problem, the solution is to use the ViewInstanceAccessControl interface instead of the ViewAccessControl iterface. Everything works fine this way.
We currently have different roles in our environments, for example in development we have roles called USR and ADM, while in production they use full names for example USER, ADMIN and ADMINISTRATOR.
My idea to resolve this problem is to use a property file and a placeholder for the rolenames, for example, this is my properties file:
role.user='USER'
role.admin='ADMIN', 'ADMINISTRATOR'
In my AppConfig I added the following annotation on top of the class:
#PropertySource("classpath:roles.properties")
public class AppConfig {
}
And in my service I'm now using:
#PreAuthorize("hasAnyRole(${role.admin})")
public Item deleteItem(int id) {
}
However, this results in the following exception:
Caused by: org.springframework.expression.spel.SpelParseException: EL1043E:(pos 12): Unexpected token. Expected 'rparen())' but was 'lcurly({)'
Because it says it's not expexting the curly brace, I also tried the following: #PreAuthorize("hasAnyRole(role.admin)") which results in:
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 11): Property or field 'role' cannot be found on object of type 'org.springframework.security.access.expression.method.MethodSecurityExpressionRoot' - maybe not public?
At least the expression itself looks valid now, but it seems it's not looking at the properties file no, but at a property of a specific class.
Does anyone have an idea to solve this? Or is there another/better solution of resolving environment-specific roles?
The Spring EL used in #PreAuthorize does only have:
Access to methods and properties of SecurityExpressionRoot.
Access method arguments (requires compilation with debug info or custom ParameterNameDiscoverer):
See this answer https://stackoverflow.com/a/3786581/883859
You can get access to other beans via # so
public interface RoleNameGetter {
String getSuperUserRole();
...
}
And
#Configuration
#PropertySource("classpath:xyz.properties")
#EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class Configuration {
#Autowired
protected Environment env;
#Bean
RoleNameGetter roleNameGetter() {
return new RoleNameGetter() {
#Override
public String getSuperUserRole() {
return env.getProperty("superuser_role_name");
}
};
}
Allows for access to role names from the property file in the Spring EL used in #PreAuthorize, like this:
#PreAuthorize("hasAnyAuthority(#roleNameGetter.getSuperUserRole(),#roleNameGetter.getNormalUserRole())")
public void end() {...}
I have an application conversion service defined in my application-context.xml.
<bean id="applicationConversionService"
class="com.myer.reporting.converter.ApplicationConversionServiceFactoryBean"
p:messageSource-ref="messageSource"/>
I am trying to inject it into one of my other beans.
<bean id="bulletinBarMessageRowMapper"
class="com.myer.reporting.dao.mapper.BulletinBarMessageRowMapper"
scope="prototype"
p:applicationConversionService-ref="applicationConversionService"/>
Where com.myer.reporting.dao.mapper.BulletinBarMessageRowMapper has the following property...
public class BulletinBarMessageRowMapper implements RowMapper<BulletinBarMessage>{
private ApplicationConversionServiceFactoryBean applicationConversionService;
public ApplicationConversionServiceFactoryBean getApplicationConversionService() {
return applicationConversionService;
}
public void setApplicationConversionService(
ApplicationConversionServiceFactoryBean applicationConversionService) {
this.applicationConversionService = applicationConversionService;
}
Seems pretty straight forward but it is failing with the following error...
Caused by: org.springframework.beans.ConversionNotSupportedException:
Failed to convert property value of type
'org.springframework.format.support.DefaultFormat
tingConversionService' to required type
'com.myer.reporting.converter.Applicatio
nConversionServiceFactoryBean' for property
'applicationConversionService'; nest ed exception is
java.lang.IllegalStateException: Cannot convert value of type [o
rg.springframework.format.support.DefaultFormattingConversionService]
to require d type
[com.myer.reporting.converter.ApplicationConversionServiceFactoryBean]
fo r property 'applicationConversionService': no matching editors or
conversion strategy found
Can someone please tell me why this would fail. I've looked up some doco and there seems to be some mention of a bean named DefaultFormattingConversionService configured automatically for us by Spring which might be interfering however I need more information on what is going wrong here.
The only other thing I can think that might be contributing to this error is that I use...
<mvc:annotation-driven conversion-service="applicationConversionService"/>
thanks
So strange thing about this is that instead of injecting via the xml I added an autowire annotation into my class and it just worked!
#Autowired
private ApplicationConversionServiceFactoryBean applicationConversionService;
Basically, I want to be able to assign objects created within filters to members in a base controller from which every controller extends. Any possible way to do that?
Here's how I tried, but haven't got to make it work.
What I'm trying to achieve is to have all my controllers extend a base controller. The base controller's constructor would be used to assign values to its members, those values being pulled from the session map. Example below.
File grails-app/controllers/HomeController.groovy:
class HomeController extends BaseController {
def index = {
render username
}
}
File grails-app/controllers/BaseController.groovy:
abstract class BaseController {
public String username
public BaseController() {
username = session.username
}
}
When running the app, the output shown is:
2010-06-15 18:17:16,671 [main] ERROR [localhost].[/webapp] - Exception sending context initialized event to listener instance of class org.codehaus.groovy.grails.web.context.GrailsContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'pluginManager' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is java.lang.RuntimeException: Unable to locate constructor with Class parameter for class org.codehaus.groovy.grails.commons.DefaultGrailsControllerClass
...
Caused by: java.lang.RuntimeException: Unable to locate constructor with Class parameter for class org.codehaus.groovy.grails.commons.DefaultGrailsControllerClass
...
Caused by: java.lang.reflect.InvocationTargetException
...
Caused by: org.codehaus.groovy.grails.exceptions.NewInstanceCreationException: Could not create a new instance of class [com.my.package.controller.HomeController]!
...
Caused by: groovy.lang.MissingPropertyException: No such property: session for class: com.my.package.controller.HomeController
at com.my.package.controller.BaseController.<init>(BaseController.groovy:16)
at com.my.package.controller.HomeController.<init>(HomeController.groovy)
...
2010-06-15 18:17:16,687 [main] ERROR core.StandardContext - Error listenerStart
2010-06-15 18:17:16,687 [main] ERROR core.StandardContext - Context [/webapp] startup failed due to previous errors
And the app won't run.
This is just an example as in my case I wouldn't want to assign a username to a string value, but rather a few objects pulled from the session map. The objects pulled from the session map are being set within filters.
The alternative I see is being able to access the controller's instance within the filter's execution. Is that possible?
Please help! Thanks a bunch!
You typically can't do much in the constructor in Grails artifacts. You can use an interceptor for this though:
abstract class BaseController {
protected String username
def beforeInterceptor = {
username = session.username
}
}
This is described in section 6.1.5 of http://grails.org/doc/latest/
You can use a request scoped service...
As a rule, I'd caution against putting state directly in a controller; controllers in general (regardless of framework) are generally intended to be stateless. I'd stick with the standard webapp state constructs like request and session to store and transfer data.
For your specific case, I'd do one of the following:
If lightweight data (primitives), I'd store them in the session and just access them as needed:
e.g. render session.username
If dynamic or database-driven data, I'd create a service and pull the data as needed:
e.g. homeService.getUser().username
As a variation to your discussion with Burt above, you could use a filter to populate a request or session value as well.