We are having performance problems on our app. It's build with JSF and omnifaces and we are monitoring with new relic.
We found a particular trace were a method that is called from the bean's constructor is invoked multiple times.
Here is the code:
import org.omnifaces.cdi.ViewScoped;
import javax.inject.Named;
#Named("bbNuevaFacturacion")
#ViewScoped
public class BBNuevaFacturacion implements Serializable{
public BBNuevaFacturacion() {
initBBNuevaFacturacion();
}
private void initBBNuevaFacturacion() {
}
}
And here is the trace:
What could be the cause of this?
Update:
On every phase it is calling the managed bean constructor
Related
I followed the rest client guide in Quarkus web site. It works fine. But when registering a global provider using the ServiceLoader pattern, as described in the specification, the CDI beans injection did not work, they are all null. I downloaded the example and simply added the following classes:
package org.acme.rest.client;
import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper;
import javax.enterprise.context.ApplicationScoped;
import javax.ws.rs.core.Response;
#ApplicationScoped
public class MyExceptionMapper implements ResponseExceptionMapper<Exception> {
#Override
public Exception toThrowable (Response response) {
return new Exception();
}
}
package org.acme.rest.client;
import org.eclipse.microprofile.rest.client.RestClientBuilder;
import org.eclipse.microprofile.rest.client.spi.RestClientBuilderListener;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
#ApplicationScoped
public class MyListener implements RestClientBuilderListener {
#Inject MyExceptionMapper myExceptionMapper;
#Override
public void onNewBuilder (RestClientBuilder builder) {
builder.register(myExceptionMapper);
}
}
I also added the file META-INF/services/org.eclipse.microprofile.rest.client.spi.RestClientBuilderListener with the content org.acme.rest.client.MyListener. The MyListener onNewBuilder method is invoked, but the injected provider MyExceptionMapper is null. How to register a global provider in Quarkus client?
Implementation of RestClientBuilderListener are not CDI beans - they are just objects that are created via the normal Java ServiceLoader mechanism when RestClientBuilder is being used.
So if you want to obtain CDI beans when onNewBuilder is called, you can do something like:
CDI.current().select(MyExceptionMapper.class).get()
Furthermore, you need to annotate MyExceptionMapper with #Provider, not #ApplicationScoped.
I have created a Service to get bean by class name.
package com.ril.service.promise.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
#Component
public class BeanService {
private static ApplicationContext applicationContextStatic;
#Autowired
BeanService(ApplicationContext applicationContext) {
applicationContextStatic = applicationContext;
}
public static <T> T getBean(Class<T> className) {
return applicationContextStatic.getBean(className);
}
}
And I am initializing a static variable link this.
import java.time.LocalDateTime;
import java.util.*;
public class Mapper {
private static Logger LOGGER = LoggerFactory.getLogger(Mapper.class);
private static PEConfigService peConfigService = BeanService.getBean(PEConfigService.class);
}
In mapper, as you see I am getting Bean in Mapper which is not spring bean class and setting it to a static variable.
The above code is working fine for me.
But I want to know will it fine always?
When you fire up a JVM and load a class for the first time (this is done by the class loader when the class is first referenced in any way) any static blocks or fields are 'loaded' into the JVM and become accessible.
So in your case the Mapper class is not reference as part of spring initialization class hence the static variables defined is not yet loaded.
You can find this reference link which could be helpful.
How static Variables loaded at run time
I am trying to build a spring boot web application. I want to refer a class from another jar. The class name is SalaryHandler.
I have done the following configuration in the class having
#SpringBootApplication annotation:
#Bean
public SalaryHandler iSalary() {
return new SalaryHandler();
}
In the class, where it is required, I have used autowiring annotation like this:
package hello;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import com.salary.SalaryHandler;
//#Service - not working
//#Component - not working
public class SalaryDelegatorImpl implements SalaryDelegator {
#Autowired
private SalaryHandler iSalary;
#Override
public void show() {
iSalary.testSalary();
}
}
The code is compiling fine, but when this iSalary object is used to call its method, nullpointer exception is thrown.
Just to note that SalaryHandler is present inside another jar and is not using any spring annotation, its code is as below:
package com.salary;
public class SalaryHandler implements ISalary {
public void testSalary() {
System.out.println("Salary test successful...");
}
}
you need to attempt Autowire with #Component. In order to get this to work, you'll have to annotate a method in your #Configuration class. Something like this should allow you to autowire the class:
#Configuration
#ComponentScan("com.package.where.my.class.is")
public class ConfigClass{
#Bean
public JPADataService jpaDataService(){
return new JPADataService();
}
}
I am able to fix this. The problem was somewhere inside code, I was calling SalaryDelegatorImpl using new operator(from inside a factory class), so that was not being managed by Spring. As a result, the #Autowired on SalaryHandler, was not working.
I changed my factory to be spring managed, and then it worked fine.
Thanks everyone for the support.
I am using Vaadin Spring 1.0.0 and trying to figure out how could I inject beans that are available only within UI scope (when the user has the page opened) into classic spring #Component beans. Simple, let's have classes:
#Component
public class A {
#Inject
private IB b;
}
#UIScope
#SpringComponent
public class B implements IB {
}
And obviously during startup:
Caused by: java.lang.IllegalStateException: No VaadinSession bound to current thread
What is the normal way how to do it? I understand the whole concept, that beans are initialized on startup when UI scope is not available, but I use common libraries which are implemented in Spring with #Component and I want to implement some of the interfaces, but I can do it only in UI scope and not during startup.
Try injecting an aop scoped proxy instead.
For example:
#Scope(value="vaadin-ui", proxyMode=ScopedProxyMode.INTERFACES)
#SpringComponent
public class B implements IB {
}
I think that should work.
You need to get it from ApplicationContext itself:
#Component
public class A {
#Autowired
private ApplicationContext context;
public B getCurrentB(){
return context.getBean(B.class);
}
}
Note that it will throw exception if there is no UI bound to the current thread (normally). In other words, you MUST make sure this method only gets called during a UI request. Any kind of listener in Vaadin should be OK, as long as you're in the same thread with the request.
Jersey: 1.12
Spring: 3.11
JDK: 1.6.0_35
Tomcat: 6..0.33
I am trying to register ExceptionMapper instances for a Jersey servlet that are instantiated by a Spring IoC container in the context of a SpringServlet, and am running into ye olde "The scope of the component class X must be a singleton" exception during the Jersey servlet initialization. I'm not in a position to post the actual code at this time, so I'm going to give the essentials of the implementation to see if something obvious jumps out at someone, or if I can be pointed at some documentation that I have missed.
The ExceptionMapper instance is essentially as follows:
// ... package definitions omitted ...
#Provider
#Singleton
public class MyExceptionMapper
implements ExceptionMapper<MyException>
{
// ... injected attributes omitted ...
#Override
public Response toResponse(MyException exception)
{
// ... specific handling logic omitted ...
return Response.status(Status.BAD_REQUEST).entity(exception.getMessage()).build();
}
}
The bean definition in applicationContext.xml is as follows, which defaults to singleton scope (and adding an explicit scope specifier doesn't seem to change the behavior):
<bean id="myExceptionMapper" class="my.package.MyExceptionMapper" />
The Spring context loader listener and SpringServlet configuration in web.xml are essentially boilerplate, and the servlet will load, initialize and operate properly with other inject attributes when the bean definition for MyExceptionMapper is commented out of the applicationContext.xml. But when the bean definition is present in applicationContext.xml, I get log messages to the effect of:
SpringProviderFactory - Registering Spring bean, myExpectionMapper, of type my.package.MyExceptionMapper as a provider class
SpringProviderFactory - Registering Spring bean, myServiceController, of type my.package.MyServiceController as a root resource class
... other root resource classes loading ...
SpringServlet - Exception occurred when initialization
java.lang.RuntimeException: The scope of the component class my.package.MyExceptionMapper must be a singleton
at som.sun.jersey.core.spi.component.ioc.IoCProviderFactory.wrap(...)
I have tried placing MyExceptionMapper in the scanned packages hierarchy to be picked up by the SpringServlet during initialization, and in a separate package hierarchy, and the results do not change.
Any assistance or guidance on this would be greatly appreciated.
My ExceptionMappers are under the structure where I'm doing component scan, and mine are simply annotated with #Component for Spring registry and #Provider for Jersey.
My component scan just looks like:
<context:component-scan base-package="com.company.web"/>
and the ExceptionMapper looks pretty much like yours:
package com.mycompany.web.provider;
import com.mycompany.exception.SpecialException;
import com.mycompany.exception.Error;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
#Provider
#Component
public class SpecialExceptionMapper implements ExceptionMapper<SpecialException> {
#Autowired
private MessageSource messageSource;
#Override
public Response toResponse(SpecialException exception) {
Error error = new Error();
error.errorMessage = messageSource.getMessage(exception.getResourceBundleKey(), exception.getArgs());
return Response.status(Response.Status.BAD_REQUEST).
entity(error).
type(MediaType.APPLICATION_JSON).
build();
}
}
Adding the scope explicitly in the spring config did the trick for me:
<bean id="exceptionMapper" class="my.pkg.MyExceptionMapper" scope="singleton" />
Stepped on same problem with Spring 3.2.3 and Jersey 2.3.1 integration.
What worked for me was combination of two:
Annotating jersey #Provider class with #Service or making it explicitly singleton in app-context xml
#Service //implies a singleton-scope
#Provider
public class UnhandledExceptionMapper implements ExceptionMapper<Throwable> {
#Override
public Response toResponse(Throwable exception) { //...
Adding package that contains provider class to jersey packages, I prefer to do this in MyApplication class:
public class MyApplication extends ResourceConfig {
public MyApplication() {
packages("com.mycompany.api.controller", "com.mycompany.api.jersey");
//....
}
}
I had the same issue, but with a MessageReaderWriterProvider class:
package my.provider.package;
...
#Provider
#Consumes({MediaType.APPLICATION_JSON, "text/json"})
#Produces({MediaType.APPLICATION_JSON, "text/json"})
public class ReRwProvider extends AbstractMessageReaderWriterProvider<Object> {
...
}
The solution was to add the package of this class in an init-param tag for Jersey's SpringServlet in web.xml:
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>my.provider.package</param-value>
</init-param>
Note that you should not define this bean in your Spring context.
Looks to me that the ExceptionMapper has to be configured as a "singleton" with Spring. If you want to use the annotation configuration you have to pay attentions because jersey has a "#Singleton" annotation too (with a different meaning of the javax.inject.Singleton interpreted by spring)
To avoid any confusion I prefer use the spring #Service annotation, that implies a singleton scope... so:
import org.springframework.stereotype.Service;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
#Service //implies a singleton-scope
#Provider
public class UnhandledExceptionMapper implements ExceptionMapper<Throwable> {
#Override
public Response toResponse(Throwable exception) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(new ErrorBean(false, exception.getMessage(), null))
.build();
}
}
I also found sometime coustom ExceptionMapper not work, and it's not always work or not work.
so i debug the jersey's source code .
class: org.glassfish.jersey.server.ServerRuntime, methed:mapException
...
final long timestamp = tracingLogger.timestamp(ServerTraceEvent.EXCEPTION_MAPPING);
**ExceptionMapper mapper = runtime.exceptionMappers.findMapping(throwable);**
if (mapper != null) {
request.getRequestEventBuilder().setExceptionMapper(mapper);
...
if the mapper is null, the coustom ExceptionMapper will be not work.
class: org.glassfish.jersey.internal.ExceptionMapperFactory methed: ExceptionMapperFactory
the Exception Mapper :(there two Exception mapping one same Exception: java.lang.Exception)
org.glassfish.jersey.server.mvc.internal.ErrorTemplateExceptionMapper#6473fc2,class java.lang.Exception
...
com.baidu.ssp.web.ws.exception.BaseExceptionMapper#7a84639c,class java.lang.Exception
it's because in MvcFeature:
#Override
public boolean configure(final FeatureContext context) {
final Configuration config = context.getConfiguration();
if (!config.isRegistered(ErrorTemplateExceptionMapper.class)) {
context.register(ErrorTemplateExceptionMapper.class);
context.register(new MvcBinder());
return true;
}
return false;
}
the ErrorTemplateExceptionMapper is also add to ExceptionMapper.
so i change my custom MapperException's genericity type : ExceptionMapper to ExceptionMapper
may be my resolution is not fit for you , the main problem is the ExceptionMapper