I have a java webapp that works just fine, but today I tried to start using spring for dependency injection. The app should run on Jetty Server but i'm stuck on this problem.
When I try to use any servlets that contain a spring dependency, I get this error:
java.lang.IllegalStateException: No resource at valueService
at org.eclipse.jetty.annotations.ResourceAnnotationHandler.handleMethod(ResourceAnnotationHandler.java:345)
at org.eclipse.jetty.annotations.ResourceAnnotationHandler.doHandle(ResourceAnnotationHandler.java:66)
at org.eclipse.jetty.annotations.AnnotationIntrospector$AbstractIntrospectableAnnotationHandler.handle(ResourceAnnotationHandler.java:345)
valueService is the name of the first dependency in the HttpServlet annotated with spring like this:
#Resource(name="valueService")
protected ValueService valueService;
which is defined in my application context as:
<bean id="valueService" class="com.nimbits.server.transaction.value.service.ValueServiceImpl" />
So, jetty is open source, so when I look at the code in jetty server ResourceAnnotationHandler.java:345 it's doing this:
else if (!Util.isEnvEntryType(paramType))
{
//if this is an env-entry type resource and there is no value bound for it, it isn't
//an error, it just means that perhaps the code will use a default value instead
// JavaEE Spec. sec 5.4.1.3
throw new IllegalStateException("No resource at "+(mappedName==null?name:mappedName));
}
so there is my error. Question: any jetty experts know why jetty is processing my spring annotation and throwing this exception. Is there a way to satisfy it? Or stop it?
Thanks, really stuck.
Ben
#Resource(name="valueService")
protected ValueService valueService;
made jetty unhappy
switching to:
#Autowired
protected ValueService valueService;
resolved it
Related
I have a Spring Boot 2.7 Web/MVC server application with profiles for different environments (DEV/QA/PROD). I have a common application.properties with shared configuration and environment specific configuration, for example, JDBC URLs in separate application-<environment>.properties on the classpath.
If the application is started without a profile being selected, it fails with a cryptic error message complaining about a jdbcUrl property missing and not being able to initialize the context - all this within a huge stack trace. This is self-explanatory for the developer, but not trivial for an operations person.
What would be the Spring way of checking if exactly one profile is selected and displaying a non-stacktrace, human (operator) friendly error message?
I am looking for something similar to what is shown if the server port is already in use.
I would like to avoid hacks and find the Spring-endorsed solution for this.
it fails with a cryptic error message complaining about a jdbcUrl property missing and not being able to initialize the context - all this within a huge stack trace
The more fundamental problem seems to be that you're fighting the built-in Boot facilities that provide assistance to humans out of the box. Instead of using #Value("${jdbcUrl}") in your code, you should inject a javax.sql.DataSource, and Boot will automatically configure one when spring.datasource.url is set. If it's not present, you'll get an error that says "no bean of DataSource is available", and the auto-config report will explain why.
You can use a postprocessor for a value . If it is not present, then log your human friendly error error message and quit the application.
e.g
#Bean
public BeanPostProcessor bpp(Environment environment) {
return new BeanPostProcessor() {
#Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(environment.getActiveProfiles()[0].equalsIgnoreCase(environment.getDefaultProfiles()[0])){
// Your Error message goes here
System.exit(1);
}
return bean;
}
};
}
Trying to register hystrix concurrency strategy fails after migrating to Spring-boot-2.0 with spring actuator enabled with java.lang.IllegalStateException stating that "Another strategy was already registered" . This is although I have not used registerConcurrencyStrategy anywhere else in my code.
I'd like to register concurrency strategy to carry-forward Log MDC context so that I'm able to log both within and outside the Hystrix wrapped method equally well, which includes thread-locals. And this used to work perfectly in spring-boot-1.5
After having migrated to spring-boot 2.0 (from 1.5), the HystrixPlugins.getInstance().registerConcurrencyStrategy(this); fails with IllegalStateException
As per https://github.com/Netflix/Hystrix/issues/1057, this issue can come if either (a) Any other code flow would have registered its own or default ConcurrencyStrategy before this is invoked (b) any call would have come via Hystrix before this is invoked
Since the above invocation is within the constructor of a class which is annotated with #Component, this should get invoked ideally before any method call happens (except initialization of other beans, including their constructors).
We even tried moving this code inside the SpringBoot Application Class's main method before invoking the SpringApplication.run(MyApplication.class, args); but that also didn't work
#Component
public class ContextCopyHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {
private static final String EVENT = "HystrixConcurrencyStrategy";
private static final String ACTION = "ContextCopy";
public ContextCopyHystrixConcurrencyStrategy(Logger logger, LoggerUtil defaultLoggerUtil) {
try {
HystrixPlugins.getInstance().registerConcurrencyStrategy(this);
} catch (IllegalStateException e) {
defaultLoggerUtil.logEvents(logger, Level.WARN, e.getMessage(), EVENT, ACTION, "", "Race condition! Could not register strategy. HystrixConcurrencyStrategy is already initialized.");
}
Expected: My registering should have happened before any other code and registering should have been successful
Actual: My registering fails with IllegalStateException
How do I make sure that my registering happens well before any other registering (which is not present in my code, but may be inside some of the libraries that I may be transitively using)
By default, Spring boot 2 accuator registers Hystrix Metric Binder beans which reset already set HystrixConcurrencyStrategy and sets HystrixConcurrencyStrategyDefault.
So, disabling that bean by
management.metrics.binders.hystrix.enabled=false
would help not resetting your custom HystrixConcurrencyStrategy
We took a close look at my maven .m2 directory classes and looked for registerConcurrencyStrategy inside all the classes in all the jars. And we found that
io.micrometer.core.instrument.binder.hystrix
was internally registering the HystrixConcurrencyStrategy with the default one.
And upon further research we found that setting the following property in application.properties:
management.metrics.binders.hystrix.enabled=false disabled the Hystrix Metrics Binder (I'm actually not sure what it does though!) and then things worked
I was using spring-boot-starter-parent v2.5.3 with Spring Cloud version 2020.0.3.
I had to manually include version for spring-cloud-starter-netflix-hystrix. I was getting "Another strategy was already registered" exception when starting my microservice. I included the
management.metrics.binders.hystrix.enabled=false
in the application.properties file and this issue got resolved.
I configured a spring boot based application to use remoting with activemq/jms. The listening part is running fine but I have problems implementing the sending part.
For the sender I went back to "classic" camel and spring because I found more working examples for this but still receive an error:
org.springframework.beans.factory.BeanNotOfRequiredTypeException:
Bean named 'myProxy' must be of type [foo.bar.YouNameIt],
but was actually of type [com.sun.proxy.$Proxy83]
This is the way I try to load the proxy definition:
ApplicationContext context = new ClassPathXmlApplicationContext("config/spring.xml");
YouNameIt youNameIt = context.getBean("myProxy", YouNameIt.class);
And this is the entry in the spring.xml:
<camel:proxy id="myProxy"
serviceInterface="foo.bar.IYouNameIt"
serviceUrl="activemq:queue:site12345" />
What am I doing wrong ?
Access the interface IYouNameIt and not the implementation class YouNameIt:
IYouNameIt youNameIt = context.getBean("myProxy", IYouNameIt.class);
See here for a full Spring remoting example.
I'm developing a Spring MVC web application (Java 6 and Spring 3.0.6 currently).
I'm starting to write some Spring integration tests using Junit4 that extend AbstractTransactionalJUnit4SpringContextTests. I invoke these either through our Maven build or in the EclipseIDE (3.7). These tests invoke Controller methods (i.e., methods annotated with #RequestHandler in a class annotated with #Controller).
All was going well until I added aspect-based logging into the controller :
// public controller methods
#Pointcut("execution(public * com.axiope.webapp.controller.*.*(..))")
private void publicControllerMethod() {
}
#Pointcut("#annotation(org.springframework.web.bind.annotation.RequestMapping)")
private void requestHandler(){}
#Pointcut("publicControllerMethod() && requestHandler() ")
private void controllerHandler(){}
// logs contoller exceptions
#AfterThrowing(
pointcut="controllerHandler()",
throwing="ex")
public void logControllerExceptions(Throwable ex) {
logger = LogFactory.getLog(ex.getClass());
logger.error("Controller exception !" + ex.getMessage());
}
Now when I run tests through Maven I get an error like :
No unique bean of type [com.axiope.webapp.controller.StructuredDocumentController]
is defined: expected single bean but found 0:
In the tests, I'm loading the controller from the applicationContext in the setUp method:
structuredDocumentController = applicationContext.getBean(
StructuredDocumentController.class);
This error doesn't happen if I comment out the aspect. I suspect it has something to do with Spring proxying the controller and then the controller class isn't identifiable by its class name. I've tried declaring the controller as a bean in applicationContext.xml but this doesn't help. This problem also occurs when running the tests in Eclipse, so it's not a problem with my Maven configuration.
My question is : how can I get the controller bean detected in the tests?
Would be really grateful for any help - is it wrong to add aspects to methods in controller classes? Should I disable aspects somehow when testing? (Although ideally I'd like to see in the integration tests that logging is working properly).
Thanks very much
Richard
Aspects are not the likely issue, you should be able to use them in the controller also without any problems.
My guess is that you are not loading up the correct context for your tests - how have you specified the application context to use for this test - is there #ContextConfiguration on your test class with the location, is the location to Root context(one specified through ContextLoaderListener) or Web application Context(one specified via DispatcherServlet).
I've been trying to get a sample JMX MXBean working in a Spring-configured webapp, but any basic attributes on the MXBean are coming up as UNDEFINED when I connect with jconsole.
Java interface/classes:
public interface IJmxBean { // marker interface for spring config, see below
}
public interface MgmtMXBean { // lexical convention for MXBeans - mgmt interface
public int getAttribute();
}
public class Mgmt implements IJmxBean, MgmtMXBean { // actual JMX bean
private IServiceBean serviceBean; // service bean injected by Spring
private int attribute = 0;
#Override
public int getAttribute() {
if(serviceBean != null) {
attribute = serviceBean.getRequestedAttribute();
}
return attribute;
}
public void setServiceBean(IServiceBean serviceBean) {
this.serviceBean = serviceBean;
}
}
Spring JMX config:
<beans>
<context:component-scan base-package="...">
<context:include-filter type="assignable" expression="...IJmxBean" />
</context:component-scan>
<context:mbean-export />
</beans>
Here's what I know so far:
The element is correctly instantiating a bean named "mgmt". I've got logging in a zero-argument public constructor that indicates it gets constructed.
is correctly automatically detecting and registering the MgmtMXBean interface with my Tomcat 6.0 container. I can connect to the MBeanServer in Tomcat with jconsole and drill down to the Mgmt MXBean.
When examining the MXBean, "Attribute" is always listed as UNDEFINED, but jconsole can tell the correct type of the attribute. Further, hitting "Refresh" in jconsole does not actually invoke the getter method of "Attribute"- I have logging in the getter method to indicate if it is being invoked (similar to the constructor logging that works) and I see nothing in the logs.
At this point I'm not sure what I'm doing wrong. I've tried a number of things, including constructing an explicit Spring MBeanExporter instance and registering the MXBean by hand, but it either results in the MBean/MXBean not getting registered with Tomcat's MBean server or an Attribute value of UNDEFINED.
For various reasons, I'd prefer not to have to use Spring's #ManagedResource/#ManagedAttribute annotations.
Is there something that I'm missing in the Spring docs or MBean/MXBean specs?
ISSUE RESOLVED: Thanks to prompting by Jon Stevens (above), I went back and re-examined my code and Spring configuration files:
Throwing an exception in the getAttribute() method is a sure way to get "Unavailable" to show up as the attribute's value in JConsole. In my case:
The Spring JMX config file I was using was lacking the default-autowire="" attribute on the root <beans> element;
The code presented above checks to see if serviceBean != null. Apparently I write better code on stackoverflow.com than in my test code, since my test code wasn't checking for that. Nor did I have implements InitializingBean or #PostConstruct to check for serviceBean != null like I normally do on almost all the other beans I use;
The code invoking the service bean was before the logging, so I never saw any log messages about getter methods being entered;
JConsole doesn't report when attribute methods throw exceptions;
The NPE did not show up in the Tomcat logs.
Once I resolved the issue with serviceBean == null, everything worked perfectly. Regardless, +1 to Jon for providing a working demo, since there are literally 50 different ways to configure MBeans/MXBeans within Spring.
I've recently built a sample Spring based webapp that very cleanly enables JMX for latest versions of Spring, Hibernate and Ehcache.
It has examples for both EntityManager based access and DAO access (including transactions!). It also shows how to do annotation based injection in order to negate having to use Spring's xml config for beans. There is even a SpringMVC based example servlet using annotations. Basically, this is a Spring based version of a fairly powerful application server running on top of any servlet engine.
It isn't documented yet, but I'll get to that soon. Take a look at the configuration files and source code and it should be pretty clear.
The motivation behind this is that I got tired of all of the crazy blog posts with 50 different ways to set things up and finally made a single simple source that people can work from. It is up on github so feel free to fork the project and do whatever you want with it.
https://github.com/lookfirst/fallback