I'm working on Business Object layer in Intershop 7 and trying to create custom business object A1PromotionBO with related business repository (extension).
I've already done Persistent Object layer (A1PromotionPO, Mgrs, EDL model, auto-generated classes, database..).
By following this Cookbook - Business Objects (https://support.intershop.com/kb/index.php/Display/27K270), i've
created package *.a1promotion.capi that contains:
- interface A1PromotionBO extends BusinessObject
- interface A1PromotionBORepository extends BusinessObjectRepository
- interface A1PromotionBORepositoryExtension extends BusinessObjectExtension<RepositoryBO>, A1PromotionBORepository
created package *.a1promotion.internal that contains:
- class ORMA1PromotionBOImpl extends AbstractExtensibleObjectBO<A1PromotionPO> implements A1PromotionBO
- class ORMA1PromotionBORepositoryImpl extends AbstractDomainRepositoryBOExtension implements A1PromotionBORepository, ObjectMapper<Object, A1PromotionBO>
- class A1PromotionBORepositoryExtensionFactory extends AbstractDomainRepositoryBOExtensionFactory
EXTENSION_ID = "A1PromotionBORepository" is defined both in interface A1PromotionBORepositoryExtension and class A1PromotionBORepositoryExtensionFactory.
And now pipelet that returns collection of A1PromotionBO fails on line when creating A1PromotionBORepository promotionBORepository:
public class GetPromotions extends Pipelet {
#Inject
private CurrentApplicationBOProvider applicationBOProvider;
/** The domain mgr. */
#Inject
private DomainMgr domainMgr;
#Override
public int execute(PipelineDictionary dict) throws PipeletExecutionException {
final ApplicationBO applicationBO = applicationBOProvider.get();
final A1PromotionBORepository promotionBORepository = applicationBO.getRepository(A1PromotionBORepositoryExtensionFactory.EXTENSION_ID);
final String promotionDomainName = dict.get("PromotionDomain");
final Domain promotionDomain = domainMgr.getDomainByName(promotionDomainName);
if (null == promotionDomain) {
throw new PipeletExecutionException("Mandatory input parameter 'ProductsDomain' not available in pipeline dictionary.");
}
final Collection<A1PromotionBO> promotions = (Collection<A1PromotionBO>)promotionBORepository.getAllPromotions();
dict.put("Promotions", promotions);
return PIPELET_NEXT;
}
}
Full stack track of exception :
Caused by: com.intershop.component.application.capi.ApplicationBOException: Can not find business object factory with extensionID A1PromotionBORepository in application ApplicationBO(Shop#A1-Site (app=a1Shop.Backoffice))
at com.intershop.component.application.internal.ApplicationBORepositoriesExtensionImpl.getRepository(ApplicationBORepositoriesExtensionImpl.java:49)
at com.intershop.component.application.internal.ApplicationBOImpl.getRepository(ApplicationBOImpl.java:222)
at hr.a1.bo.promotion.pipelet.GetPromotions.execute(GetPromotions.java:44)
at com.intershop.beehive.core.internal.pipeline.PipeletNode.executeNode(PipeletNode.java:346)
... 42 more
Related
I have created Oracle service with #CordaService annotation
I am getting Exception while installing Corda Service.
It will not get defined service type, got size 0 in List object in first argument of constructor.
public NumberVerifierOracle(PluginServiceHub services){
this(services.getMyInfo().serviceIdentities(NumberVerifierOracleType.getNumberVerifierOracleType().getServiceType()).get(0),services);
}
The defined service type is:
public class NumberVerifierOracleType {
private static ServiceType serviceType;
private static NumberVerifierOracleType numberVerifierOracleType = new NumberVerifierOracleType();
private NumberVerifierOracleType(){
serviceType = ServiceType.Companion.getServiceType("com.template.oracle.service","numberVerifierService_NumberVerifierOracle");
}
public static NumberVerifierOracleType getNumberVerifierOracleType() {
return numberVerifierOracleType;
}
public ServiceType getServiceType() {
return serviceType;
}
}
The Package hierarchy is:
com.template.oracle.service.NumberVerifierOracle class
I have resolved this error by making service with Public modifier.
Like this:
public static ServiceType type;
static{
type= NumberVerifierOracleType.getNumberVerifierOracleType().getServiceType();
}
It will not work if we have private modifier and use directly getter method.
I have a simple spring boot app and I'm trying to get it up and running. The config consists of an app context ( applicationContext.xml) XML with a bunch of beans in it. I have a Spring application class:
#SpringBootApplication
#Configuration
#ImportResource("classpath:applicationContext.xml")
public class WebCheckApplication {
private static final Logger logger = Logger.getLogger(WebCheckApplication.class);
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(WebCheckApplication.class, args);
if (logger.isDebugEnabled()) {
logger.debug("Let's inspect the beans provided by Spring Boot:");
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
logger.debug(beanName);
}
}
}
}
And I have a #WebListener class that grabs a few beans from the WebContext from within the ServletContext:
#WebListener
public class SystemPropertiesContextInitializer extends SysPropsAlertsFetcher implements ServletContextListener {
private static final Logger logger = Logger.getLogger(SystemPropertiesContextInitializer.class);
#Override
public void contextDestroyed(ServletContextEvent sce) {
//remove the SystemProperties and alert types map object from context
sce.getServletContext().removeAttribute(BaseAuthenticatedController.SYSPROPS_KEY);
sce.getServletContext().removeAttribute(BaseAuthenticatedController.ALERT_TYPES_MAP_KEY);
}
#Override
public void contextInitialized(ServletContextEvent sce) {
SysPropsDataAccess = (SystemPropertiesDataAccess) WebApplicationContextUtils.getRequiredWebApplicationContext(sce.getServletContext()).getBean("SystemPropertiesDataAccess");
AlertsDataAccess = (AlertDataAccess) WebApplicationContextUtils.getRequiredWebApplicationContext(sce.getServletContext()).getBean("AlertsDataAccess");
fetchObjects(sce.getServletContext());
}
}
When I attempt to start the app, I get the following error:
SEVERE: Exception sending context initialized event to listener instance of class web.SystemPropertiesContextInitializer
java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?
at org.springframework.web.context.support.WebApplicationContextUtils.getRequiredWebApplicationContext(WebApplicationContextUtils.java:83)
at .web.SystemPropertiesContextInitializer.contextInitialized(SystemPropertiesContextInitializer.java:31)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4994)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5492)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
and it occurs at this line:
SysPropsDataAccess = (SystemPropertiesDataAccess) WebApplicationContextUtils.getRequiredWebApplicationContext(sce.getServletContext()).getBean("SystemPropertiesDataAccess");
It looks like Spring isn't creating a WebApplicationContext.
Greater than or equal 1.3.0.RC1 use #ServletComponentScan
#ServletComponentScan // <-- This scans for EJB #WebFilter, #WebListener and #WebServlet
#SpringBootApplication
#ImportResource("classpath:applicationContext.xml")
public class WebCheckApplication {
Less than or equal 1.2.x use #Component to scan for listener
#Component // <-- This allows the component to be found by #ComponentScan inside of #SpringBootApplication
#WebListener
public class MojoSystemPropertiesContextInitializer extends MojoSysPropsAlertsFetcher implements ServletContextListener {
War Deploy extend SpringBootServletInitializer
public class WebCheckApplication extends SpringBootServletInitializer {
In 1.3.0.RC1 #ServletComponentScan was added so simply annotating your main application config should allow these to be picked up. Otherwise adding #Component to your ServletContextListener should work
This link is a discussion on how they currently handle #WebFilter how they decided to handle #WebFilter and they also discuss SpringBootServletInitializer and how this would pick process each item twice if both were to be used. Also links to the commits that implement the new feature.
https://github.com/spring-projects/spring-boot/issues/2290
If you intend to deploy your application as a war file you may also have your main configuration extend SpringBootServletInitializer
http://docs.spring.io/spring-boot/docs/current/reference/html/howto-traditional-deployment.html
All that was needed was to make the Application class extend SpringBootServletInitializer
Good evening everybody,
I have a EJB class. This class has 2 attributes are EJB, with private access, and "injected" with EJB annotation #EJB. This class has no defined constructor.
I want to test this class by using Mockito.
I have 2 problems :
1) the 2 attributes are with private access
2) Even when i want to put a defined constructor with the 2 EJB attributes as parameters, it does not work in my TestNG class
In my TestNG class,
i only want instantiate my class of course,
and also her 2 EJB attributes as 2 mocks.
And i do not succeed.
Thank you very much,
Thomas
This is the class.
package fr.nomenclature.service;
#Stateless
#Local
#TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class TraitementNomenclaturesImpl implements TraitementNomenclatures {
private static final Logger LOG = LoggerFactory.getLogger(TarificationFactureImpl.class);
#EJB(name = "AccesNomenclatures-interne-ebx")
private transient AccesNomenclatureEBX accesEbx;
#EJB(name = "AccesElementFacturation-interne-ebx")
private transient AccesElementFacturationEBX accesRefEbx;
/*
* (non-Javadoc)
*
* #see
* fr.atom.referentiel.sante.nomenclature.service.TraitementNomenclature#extraireNomenclaturesDesPrestations(java
* .util.List, java.util.Date, fr.atom.configuration.SoapContext)
*/
#Override
public ContenusNomenclatures extraireNomenclaturesDesPrestations(
final List<PrestationDeSante<? extends Identifiant>> pPrestations, final Date pDateTraitement,
final SoapContext pContext) {
.......
}
}
As far my knowledge #Autowired object is initialized when the application start and this is handled by spring and scope will depends on what we specify in bean.xml and #Autowired object are available right before they are used actually in the code.
My question is in below code I want that for every call to SAController class a new SuperAdminDetailsManager object should be created. So I configure scope = "prototype" is that correct so that for every call to controller a new SuperAdminDetailsManager object will be created.
Controller Class
#Controller
public class SAController {
#Autowired
private SuperAdminDetailsManager superAdminDetailsManager;
private static final Logger logger = LoggerFactory.getLogger(SAController.class);
private ApplicationContext context = null;
#RequestMapping(value = "/sadminlogin", method = RequestMethod.GET)
public String redirectLogin(ModelMap map) {
map.addAttribute("superAdmin", new SuperAdmin());
return "sa_login";
}
public void setSuperAdminDetailsManager(
SuperAdminDetailsManager superAdminDetailsManager) {
this.superAdminDetailsManager = superAdminDetailsManager;
}
}
beans.xml Configuration
context = new ClassPathXmlApplicationContext("beans.xml");
<bean id="superAdminManager" class="com.serviceimpl.SuperAdminDetailsManagerImpl" scope="prototype"></bean>
One more question when I can get the object using ClassPathXmlApplicationContext why do I need autowired
Object using ClassPathXmlApplicationContext
superAdminDetailsManager = (SuperAdminDetailsManager )context.getBean("superAdminManager");
I need to audit invocations of ejb beans. Saying audit I mean write informations such as current logged user, method name, additional description to a database. I decided to do it by use of CDI decorator:
#Decorator
public class AccountServiceBeanDecorator implements AccountService {
#Inject
#Delegate
#Any
AccountService accountService;
#EJB
private AuditService auditService;
#Override
public Account createAccount(Account account) {
auditService.saveAudit("Method: createAccount", currentUser, "Creating account by admin");
return accountService.createAccount(account);
}
}
and the decorated class:
#Stateless
public class AccountServiceBean implements AccountService {
#Override
public Account createAccount(Account account) {
...
}
}
Now if I call AccountService from another ejb stateless bean, what will happen with transaction?:
#Stateless
public ApplicationFacadeBean implements ApplicationFacade {
#EJB
private AccountService accountService;
#Override
public Account createAccount(Account account) {
return accountService.createAccount(account);
}
}
I wanted to log transaction status in decorator (AccountServiceBeanDecorator) and decorated class (AccountServiceBean), so I injected TransactionSynchronizationRegistry as a resource in both classes:
#Decorator
public class AccountServiceBeanDecorator implements AccountService {
#Inject
#Delegate
#Any
AccountService accountService;
#EJB
private AuditService auditService;
#Resource
private TransactionSynchronizationRegistry reg;
#Override
public Account createAccount(Account account) {
log.info("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
log.info("tx ({}): {}", new Object[] {reg.getTransactionStatus(), reg.getTransactionKey()});
log.info("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
auditService.saveAudit("Method: createAccount", currentUser, "Creating account by admin");
return accountService.createAccount(account);
}
}
and
#Stateless
public class AccountServiceBean implements AccountService {
#Resource
private TransactionSynchronizationRegistry reg;
#Override
public Account createAccount(Account account) {
log.info("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
log.info("tx ({}): {}", new Object[] {reg.getTransactionStatus(), reg.getTransactionKey()});
log.info("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
...
}
}
I received strange behavior:
log from decorator
tx (0): JavaEETransactionImpl: txId=6 nonXAResource=null jtsTx=null localTxStatus=0 syncs=[com.sun.ejb.containers.ContainerSynchronization#68fb15d0]]]
NullPointerException on second log (reg is null).
Can anybody explain it to me? Wheter AccountServiceBean class is called within the same transaction as ApplicationFacade?
Thank you
first: i would not mixing ejbs with cdi interceptors. ejbs has it on interceptor implementations.
second: interceptors are executed in the same transaction as the ejb where the interceptor is around.
possible solution:
create a correct ejb interceptor
put the interceptor around the method / class
create a second ejb (MyLoggerBean) with a method like this logToDatabase(String message) and annotate this method with #TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
inside the interceptor create a class member like this: #EJB private MyLoggerBean loggerBean
inside your #AroundInvoke annotated method you could call loggerBean. logToDatabase(...)
this would create a new transaction from inside the current transaction of the ejb where the interceptor is around
--> i know my english is not very good. but i hope that you understand what i think should work. if i have the time, i make e example on github...
Hmm... what container are you using? Generally I wouldn't suspect a CDI decorator to work on an EJB... I can't think of anything in the JEE spec that I've encountered that would give evidence either way.
Faced with your problem though, I did this with an interceptor, not a decorator. These are supported by the EJB spec... Anyway, here's my code, you would need to grab the variables from the context in your case:
import java.lang.reflect.Method;
import javax.inject.Inject;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;
public class InvocationCountInterceptor {
#Inject
private InvocationCounter counter;
#AroundInvoke
public Object intercept(InvocationContext ctx) throws Exception {
Object returnValue = ctx.proceed();
Class<? extends Object> className = ctx.getTarget().getClass();
Method methodName = ctx.getMethod();
counter.incrementCounter(className, methodName);
return returnValue;
}
}
Then whatever EJB or EJB Method you want to audit, I just added this: #Interceptors(InvocationCountInterceptor.class)