Let i need to create a nodes in the alfresco repository at the bootstrap phase to use them later, how can i do that?
I use the .amp file to install the extension customization into alfresco.war, so i have
module-context.xml and inside it i write an import statement refer to the bootstrap-context.xml which have a bean like this
<bean id="com.ds.module.extensions.Core.securityRequirementBootstrap"
class="com.ds.ui.bean.dialog.module.SecurityRequirementBootstrap"
init-method="init">
<property name="nodeService">
<ref bean="NodeService" />
</property>
<property name="searchService">
<ref bean="SearchService" />
</property>
<property name="authenticationService">
<ref bean="AuthenticationService" />
</property>
<property name="transactionService">
<ref bean="transactionService" />
</property>
<property name="personService">
<ref bean="PersonService" />
</property>
</bean>
and as you see the bean have set of properties injected from a spring framework.
SecurityRequirementBoostrap is a class and it like as this
public class SecurityRequirementBootstrap {
public void init() throws Exception{
AuthenticationUtil.runAs(new RunAsWork<String>() {
public String doWork() throws Exception {
try {
transaction = transactionService.getUserTransaction();
transaction.begin();
if(!authenticationService.authenticationExists("admin")){
authenticationService.createAuthentication("admin", new char [] {'a','d','m','i','n'});
}
if(!personService.personExists("admin")){
personService.createPerson(createDefaultProperties("admin", "admin", "admin", "admin#localhost", "admin"));
}
authenticationService.authenticate("admin", new char [] {'a','d','m','i','n'});
NodeUtil.checkSecurityPreRequesite(searchService,nodeService);
transaction.commit();
return "";
}
catch(Throwable e){
transaction.rollback();
e.printStackTrace();
}
return "";
}
}, "admin");
}
private Map<QName, Serializable> createDefaultProperties(String userName, String firstName, String lastName,
String email, String password) {
HashMap<QName, Serializable> properties = new HashMap<QName, Serializable>();
properties.put(ContentModel.PROP_USERNAME, userName);
properties.put(ContentModel.PROP_FIRSTNAME, firstName);
properties.put(ContentModel.PROP_LASTNAME, lastName);
properties.put(ContentModel.PROP_EMAIL, email);
properties.put(ContentModel.PROP_PASSWORD, password);
return properties;
}
private NodeService nodeService;
private SearchService searchService;
private UserTransaction transaction;
private TransactionService transactionService;
private MutableAuthenticationService authenticationService;
private PersonService personService;
public static Logger LOGGER = Logger.getLogger(SecurityRequirementBootstrap.class);
public PersonService getPersonService() {
return personService;
}
public void setPersonService(PersonService personService) {
this.personService = personService;
}
public MutableAuthenticationService getAuthenticationService() {
return authenticationService;
}
public void setAuthenticationService(
MutableAuthenticationService authenticationService) {
this.authenticationService = authenticationService;
}
public TransactionService getTransactionService() {
return transactionService;
}
public void setTransactionService(TransactionService transactionService) {
this.transactionService = transactionService;
}
public NodeService getNodeService() {
return nodeService;
}
public void setNodeService(NodeService nodeService) {
this.nodeService = nodeService;
}
public SearchService getSearchService() {
return searchService;
}
public void setSearchService(SearchService searchService) {
this.searchService = searchService;
}
}
As you can see in the init method i aimed to authenticate the admin user and after that i will use a NodeUtil class to create the nodes required. NodeUtil is a big class but it is work fine regardless of bootstrapping.
In all cases i have an exception once the alfresco bootstrapped and the exception look like this
$ org.alfresco.repo.audit.model.AuditModelException: 07220000 No registered audit data extractor exists for 'org_alfresco_module_dod5015_userRolesExtractor'.
at org.alfresco.repo.audit.model.AuditModelRegistryImpl$AuditModelRegistryState.cacheAuditElements(AuditModelRegistryImpl.java:524)
at org.alfresco.repo.audit.model.AuditModelRegistryImpl$AuditModelRegistryState.access$500(AuditModelRegistryImpl.java:240)
at org.alfresco.repo.audit.model.AuditModelRegistryImpl$AuditModelRegistryState$1.execute(AuditModelRegistryImpl.java:389)
at org.alfresco.repo.audit.model.AuditModelRegistryImpl$AuditModelRegistryState$1.execute(AuditModelRegistryImpl.java:375)
at org.alfresco.repo.transaction.RetryingTransactionHelper.doInTransaction(RetryingTransactionHelper.java:381)
at org.alfresco.repo.audit.model.AuditModelRegistryImpl$AuditModelRegistryState$2.doWork(AuditModelRegistryImpl.java:416)
at org.alfresco.repo.audit.model.AuditModelRegistryImpl$AuditModelRegistryState$2.doWork(AuditModelRegistryImpl.java:413)
at org.alfresco.repo.security.authentication.AuthenticationUtil.runAs(AuthenticationUtil.java:508)
at org.alfresco.repo.audit.model.AuditModelRegistryImpl$AuditModelRegistryState.start(AuditModelRegistryImpl.java:412)
at org.alfresco.repo.management.subsystems.AbstractPropertyBackedBean.start(AbstractPropertyBackedBean.java:458)
at org.alfresco.repo.management.subsystems.AbstractPropertyBackedBean.start(AbstractPropertyBackedBean.java:440)
at org.alfresco.repo.management.subsystems.AbstractPropertyBackedBean.getState(AbstractPropertyBackedBean.java:221)
at org.alfresco.repo.audit.model.AuditModelRegistryImpl.getState(AuditModelRegistryImpl.java:165)
at org.alfresco.repo.audit.model.AuditModelRegistryImpl.getAuditPathMapper(AuditModelRegistryImpl.java:201)
at org.alfresco.repo.audit.AuditComponentImpl.areAuditValuesRequired(AuditComponentImpl.java:232)
at org.alfresco.repo.audit.AuditMethodInterceptor.invoke(AuditMethodInterceptor.java:129)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy56.authenticationExists(Unknown Source)
at com.ds.ui.bean.dialog.module.SecurityRequirementBootstrap$1.doWork(SecurityRequirementBootstrap.java:29)
at com.ds.ui.bean.dialog.module.SecurityRequirementBootstrap$1.doWork(SecurityRequirementBootstrap.java:1)
at org.alfresco.repo.security.authentication.AuthenticationUtil.runAs(AuthenticationUtil.java:508)
at com.ds.ui.bean.dialog.module.SecurityRequirementBootstrap.init(SecurityRequirementBootstrap.java:24)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeCustomInitMethod(AbstractAutowireCapableBeanFactory.java:1529)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1468)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1398)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:512)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:450)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:290)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:287)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:189)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:557)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:842)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:416)
at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:261)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:192)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47)
at org.alfresco.web.app.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:63)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3972)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4467)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:546)
at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:637)
at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.java:563)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:498)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1277)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:321)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:785)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
at org.apache.catalina.core.StandardService.start(StandardService.java:519)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
at org.apache.catalina.startup.Catalina.start(Catalina.java:581)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)
So, can anyone help me to solve this problem.
Thanks
Mohammed Amr | Digital Series | Senior System Developer
I'd suggest not using the Node Service to do this.
If you look at how new system folders are added into Alfresco (during upgrades and fresh installs), they're normally done as ACPs. By using an ACP, you don't need to take care of the special cases during the bootstrap phase (when not all of the repo is ready, and not all the services are fully available). Instead, you just point your bootstrap context file at an ACP, which has the content and nodes, and away you go.
If you want a simple example for creating a folder, you could try looking at /config/alfresco/bootstrap/scheduledActionsFolder.xml in a standard install for a simple guide.
Related
I am a beginner to Spring Boot/MVC. I have been trying to build a very basic example of querying a table containing master data for doctors.However I am repeatedly getting "java.lang.NullPointerException".Most probably because jdbcTemplate object is not getting initialized.
Some of the other users also faced this issue however in their case the problem was resolved after either including starter-jdbc jar or after removing usage of new operator to create jdbctemplate object.I have already factored these suggestions in my code. Any help on the matter would be appreciated.My code snippets are as following:
1. application.properties :
server.port=8181
spring.datasource.url = jdbc:mysql://localhost:3306/my_sample_schema
spring.datasource.username = qwerty
spring.datasource.password = qwerty
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.driverClassName=com.mysql.jdbc.Driver
debug=true
2. Test123Application.java
package com.example;
....all imports...
#SpringBootApplication
public class Test123Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Test123Application.class, args);
}
}
3.Testcontroller.java
package com.example.controller;
....all imports...
#Controller
public class TestController {
#RequestMapping(value = "/")
public String demofunction(){
return "dummytemplate";
}
#RequestMapping("/default")
public String demofunction2(Model model){
Docrepo docrepo = new Docrepoimpl();
List<Docmaster> listContact = docrepo.list();
model.addAttribute("listContact", listContact);
return "dummytemplate2";
}
}
4. Docrepoimpl.java
package com.example.repository;
----all imports---
#Configuration
#Repository
public class Docrepoimpl implements Docrepo{
#Autowired
private JdbcTemplate jdbcTemplate;
public void adddoctor(Docmaster doc){
String sql = "INSERT INTO docmastertable (docid,name,yoe,speciality,degree,college,hospital,regno)"
+ " VALUES (?,?,?,?,?,?,?,?)";
jdbcTemplate.update(sql, doc.getdocid(), doc.getname(),doc.getyoe(), doc.getspeciality(),doc.getdegree(),doc.getcollege(),doc.gethospital(),doc.getregno());
}
public List <Docmaster> list(){
String sql = "SELECT * FROM docmastertable";
if(jdbcTemplate != null)
System.out.println("jdbc seems ok...");
else
System.out.println("jdbc is null...");
List<Docmaster> listContact = jdbcTemplate.query(sql, new RowMapper<Docmaster>() {
#Override
public Docmaster mapRow(ResultSet rs, int rowNum) throws SQLException {
Docmaster doc = new Docmaster();
doc.setdocid(rs.getString("docid"));
doc.setname(rs.getString("name"));
doc.setyoe(rs.getInt("yoe"));
doc.setspeciality(rs.getString("speciality"));
doc.setdegree(rs.getString("degree"));
doc.setcollege(rs.getString("college"));
doc.sethospital(rs.getString("hospital"));
doc.setregno(rs.getString("regno"));
return doc;
}
});
return listContact;
}
}
Error Dump:
java.lang.NullPointerException: null
at com.example.repository.Docrepoimpl.list(Docrepoimpl.java:52) ~[classes/:na]
at com.example.controller.TestController.demofunction2(TestController.java:43) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_40]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_40]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_40]
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_40]
...
Actually you are creating the repo directly in your controller class with a new statement. I'd recommend to also inject your Repo into your controller class by creating a local member and annotate it with #Autowired. If you don't want to follow this way you can also ask the Context to return a ready to use bean.
It always happens when you try to access Spring class that are not managed by the Spring Boot framework AKA the Spring boot container.
With the following line you can get any spring boot class for which the #Autowired does not work.
Here is a class that i used to access JdbcTemplate without #Autowired.
public class MysqlServiceJava {
// You don't need #Autowired
JdbcTemplate jdbcTemplate;
public MysqlServiceJava() {
// Get JdbcTemplate through Context container AKA !! THE MAGIC !!
jdbcTemplate = ApplicationContextHolder.getContext().getBean(JdbcTemplate.class);
}
public List<Integer> findAllEasyId(){
List<Integer> Ids = new ArrayList<>();
String sql = "SELECT id FROM master_table";
jdbcTemplate.query(
sql, new Object[] {},
(rs, rowNum) -> new MasterTable(rs.getInt("id"))
).forEach(
masterTable ->
Ids.add(masterTable.getId()) // add Id to Ids List array
);
return Ids;
}
}
class MasterTable {
private Integer id;
public MasterTable(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
#Override
public String toString() {
return "MasterTable{" +
"id=" + id +
'}';
}
public void setId(Integer id) {
this.id = id;
}
}
Thumbs up if you like =)
I am trying to code a simple AspectJ implementation but the Advice is not getting executed.
The LoggingAspect Class is getting initiated as in the console I can see s.o.p of constructor
This is logging aspect
getting printed when the ApplicationContext is loaded and controllerAspect is initialized. When I run the main method , the output is
Name: John Age :12
What I was expecting was the s.o.p for #Before advice should be printed first and then for getter methods #AfterReturning s.o.p should be printed.
There is no compilation error , the program is running but advice is not getting executed.
According to the pointcut, the advice should get implemented on all methods of the Customer class.
I went through some of the similar problems posted here , but could not figure out what was the issue with my implementation.
Can any one figure the mistake I am making and provide the resolution ?
Here is the snippet servlet-context.xml
<context:component-scan base-package="main.com.controller"/>
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven></annotation-driven>
<aop:aspectj-autoproxy/>
<!-- AOP support -->
<bean id='controllerAspect' class='main.com.logging.LoggingAspect' />
<beans:bean id="cust" class="main.com.dtos.Customer"</beans:bean>
<resources mapping="/resources/**" location="/resources/" />
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/"/>
<beans:property name="suffix" value=".jsp"/>
</beans:bean>
The LoggingAspect class is :
#Aspect
public class LoggingAspect {
public LoggingAspect() {
System.out.println("This is logging aspect");
}
#Pointcut("execution(* com.dtos.*.*(..))")
public void getMethodPointcut() {}
#AfterReturning(pointcut = "getMethodPointcut()", returning="retVal")
public void afterReturningAdvice(Object retVal) {
System.out.println("Returning:" + retVal.toString() );
}
#Before("getMethodPointcut()")
public void printBefore(JoinPoint jp ) {
System.out.println("Before calling method:"+jp.getSignature());
}
Customer class is :
#Size(max=30, min=3)
#NotNull
private String name;
#Max(150)
#NotNull
private String age;
public Customer() {}
public Customer(String sName, String sAge) {
name = sName;
age = sAge;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
#Override
public String toString() {
return "Customer [name=" + name + ", age=" + age + "]";
}
Main method is :
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("classpath:servlet- context.xml");
Customer cust = (Customer)context.getBean("cust");
cust.setAge("12");
cust.setName("John");
String name = cust.getName();
String age = cust.getAge();
System.out.println("Name: "+name+" Age :"+age);
}
Aspectj POM dependencies
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.7.4</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.7.4</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.7.4</version>
</dependency>
Just so as to enable you to close the question by accepting an answer, I am repeating my answer from the comment:
Your Spring config implies it is main.com.dtos.Customer, your aspect pointcut is looking for com.dtos.* (without main. prefix) though.
Attempting to get pagination on datatables using Thymeleaf and Dandelion. According to the docs I need to update a few things:
web.xml (javaconfig attempt further down)
<!-- Dandelion filter definition and mapping -->
<filter>
<filter-name>dandelionFilter</filter-name>
<filter-class>com.github.dandelion.core.web.DandelionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>dandelionFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Dandelion servlet definition and mapping -->
<servlet>
<servlet-name>dandelionServlet</servlet-name>
<servlet-class>com.github.dandelion.core.web.DandelionServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dandelionServlet</servlet-name>
<url-pattern>/dandelion-assets/*</url-pattern>
</servlet-mapping>
SpringTemplateEngine #Bean (skipped as I already have the Thymeleaf template Engine)
<bean id="templateEngine" class="org.thymeleaf.spring3.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver" />
<property name="additionalDialects">
<set>
<bean class="com.github.dandelion.datatables.thymeleaf.dialect.DataTablesDialect" />
</set>
</property>
</bean>
My knowledge of Spring is still extremely shaky but I have to replace the web.xml components (least I think I can do it this way):
public class Initializer extends
AbstractAnnotationConfigDispatcherServletInitializer...
#Override
protected Class<?>[] getServletConfigClasses() {
logger.debug("Entering getServletConfigClasses()");
return new Class<?>[] { ThymeleafConfig.class, WebAppConfig.class, DandelionServlet.class };
}
#Override
protected Filter[] getServletFilters() {
return new Filter[] { new DandelionFilter(),
new DelegatingFilterProxy("springSecurityFilterChain") };
}
My ThymeleafConfig:
#Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
templateEngine.addDialect(dataTablesDialect());
return templateEngine;
}
#Bean
public ThymeleafViewResolver thymeleafViewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
return resolver;
}
#Bean
public DataTablesDialect dataTablesDialect() {
return new DataTablesDialect();
}
My security settings:
.antMatchers("/dandelion-assets/**").permitAll()
.antMatchers("/datatablesController/**").permitAll()
I get the following in my logs after both dialects load:
[THYMELEAF] TEMPLATE ENGINE CONFIGURED OK
INFO org.thymeleaf.TemplateEngine - [THYMELEAF] TEMPLATE ENGINE INITIALIZED
When the page loads:
DEBUG com.github.dandelion.datatables.core.configuration.StandardConfigurationLoader - No custom configuration. Using default one.
DEBUG com.github.dandelion.datatables.core.configuration.StandardConfigurationLoader - Resolving groups for the locale en_US...
DEBUG com.github.dandelion.datatables.core.configuration.StandardConfigurationLoader - 1 groups declared [global].
DEBUG com.github.dandelion.datatables.core.configuration.StandardConfigurationLoader - Resolving configurations for the locale en_US...
DEBUG com.github.dandelion.datatables.core.configuration.StandardConfigurationLoader - Group 'global' initialized with 0 properties
DEBUG com.github.dandelion.datatables.core.configuration.StandardConfigurationLoader - 1 group(s) resolved [global] for the locale en_US
DEBUG com.github.dandelion.datatables.thymeleaf.processor.el.TableFinalizerElProcessor - No configuration to apply, i.e. no 'dt:conf' has been found in the current template.
DEBUG com.github.dandelion.datatables.core.generator.configuration.DatatablesGenerator - Generating DataTables configuration ..
DEBUG com.github.dandelion.datatables.core.generator.configuration.DatatablesGenerator - DataTables configuration generated
DEBUG com.github.dandelion.datatables.core.generator.WebResourceGenerator - Loading extensions...
DEBUG com.github.dandelion.datatables.core.extension.ExtensionLoader - Scanning built-in extensions...
DEBUG com.github.dandelion.datatables.core.generator.WebResourceGenerator - Transforming configuration to JSON...
DEBUG com.github.dandelion.datatables.thymeleaf.processor.el.TableFinalizerElProcessor - Web content generated successfully
DEBUG com.github.dandelion.datatables.core.configuration.DatatablesConfigurator - Initializing the Javascript generator...
Only warning I get:
WARN com.github.dandelion.core.asset.AssetMapper - No location found for delegate on AssetStorageUnit [name=dandelion-datatables, version=0.10.0, type=js, dom=null, locations={delegate=dandelion-datatables.js}, attributes=null, attributesOnlyName=[]]
DEBUG com.github.dandelion.core.asset.cache.AssetCacheManager - Retrieving asset with the key 6c075191955bbb1ecbd703380e648817806cf15b/dandelion-datatables-0.10.0.js
DEBUG com.github.dandelion.core.asset.cache.AssetCacheManager - Storing asset under the key 6c075191955bbb1ecbd703380e648817806cf15b/dandelion-datatables-0.10.0.js
WARN com.github.dandelion.core.asset.AssetMapper - No location found for delegate on AssetStorageUnit [name=dandelion-datatables, version=0.10.0, type=js, dom=null, locations={delegate=dandelion-datatables.js}, attributes=null, attributesOnlyName=[]]
DEBUG com.github.dandelion.core.asset.cache.AssetCacheManager - Retrieving asset with the key 6c075191955bbb1ecbd703380e648817806cf15b/dandelion-datatables-0.10.0.js
DEBUG com.github.dandelion.core.asset.cache.AssetCacheManager - Storing asset under the key 6c075191955bbb1ecbd703380e648817806cf15b/dandelion-datatables-0.10.0.js
And finally:
<table class="table table-striped table-bordered table-hover"
dt:table="true" id="myTable" dt:pagination="true">
When the page loads, the data loads but it isn't paginated; where'd I go wrong?
Just tried to set this up.
Here follows my working configuration.
WebConfig.java
#Configuration
#ComponentScan(basePackages = { "com.github.dandelion.datatables.web" })
#EnableWebMvc
#Import({ ThymeleafConfig.class })
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
Here is the imported ThymeleafConfig.java class:
#Configuration
public class ThymeleafConfig {
#Bean
public ServletContextTemplateResolver templateResolver() {
ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".html");
resolver.setTemplateMode("HTML5");
resolver.setCacheable(false);
return resolver;
}
#Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver(templateResolver());
engine.addDialect(new DandelionDialect());
engine.addDialect(new DataTablesDialect());
return engine;
}
#Bean
public ThymeleafViewResolver thymeleafViewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
return resolver;
}
}
Then the root configuration. Quite hairy as you can see.
RootConfig.java
#Configuration
#ComponentScan(basePackages = { "com.github.dandelion.datatables.service", "com.github.dandelion.datatables.repository" })
public class RootConfig {
}
And finally, the app initializer. Make sure to have well configured the Dandelion components (DandelionFilter and DandelionServlet).
ApplicationInitializer.java
public class ApplicationInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
// Register the Root application context
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(RootConfig.class);
// Register the Web application context
AnnotationConfigWebApplicationContext mvcContext = new AnnotationConfigWebApplicationContext();
mvcContext.register(WebConfig.class);
// Context loader listener
servletContext.addListener(new ContextLoaderListener(rootContext));
// Register the Dandelion filter
FilterRegistration.Dynamic dandelionFilter = servletContext.addFilter("dandelionFilter", new DandelionFilter());
dandelionFilter.addMappingForUrlPatterns(null, false, "/*");
// Register the Spring dispatcher servlet
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("springServlet", new DispatcherServlet(mvcContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
// Register the Dandelion servlet
ServletRegistration.Dynamic dandelionServlet = servletContext.addServlet("dandelionServlet", new DandelionServlet());
dandelionServlet.setLoadOnStartup(2);
dandelionServlet.addMapping("/dandelion-assets/*");
}
}
You can see the full sample application here.
Hope this helps!
(Disclaimer required by StackOverflow: I'm the author of Dandelion)
I am trying to do a simple OSGi service using Declarative Services on a local Glassfish server. The plugin which provides is always active.
I got trouble with the injection into my servlet that consumes my service, the reference is null when the servlet gets called because it isn't the same object that the one which got injected with the service reference.
I tested it by putting a breakpoint into my reference setter, and I saw my service getting injected, but when I click on the button that calls my servlet into my application the service reference is null because it isn't the same object (i.e. gets injected in servlet_Instance #1 but invoke the method on servlet_Instance #2. I must be missing a little detail, because I can find and use my service when doing
final BundleContext bundleContext = FrameworkUtil.getBundle(getClass()).getBundleContext();
loggingTestServiceInterface = (LoggingTestServiceInterface) bundleContext.getService(bundleContext
.getServiceReference(LoggingTestServiceInterface.class.getName()));
The plugin used to generate my XMLs files : maven-scr-plugin
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<version>1.14.0</version>
<executions>
<execution>
<id>generate-scr-scrdescriptor</id>
<goals>
<goal>scr</goal>
</goals>
</execution>
</executions>
<configuration>
<supportedProjectTypes>
<supportedProjectType>war</supportedProjectType>
<supportedProjectType>jar</supportedProjectType>
<supportedProjectType>bundle</supportedProjectType>
</supportedProjectTypes>
</configuration>
</plugin>
This is my service class
#Component(immediate = false, name = "Shikashi", service = {LoggingTestServiceInterface.class}, enabled = true)
public class LoggingTestService implements LoggingTestServiceInterface
{
private final LoggerUtils loggerUtils = new LoggerUtils();
public LoggingTestService()
{
}
#Activate
public void start(final BundleContext bundleContext)
{
System.out.println("StartTest Service Fune");
}
#Deactivate
public void stop()
{
System.out.println("Stop Test Service Jitensha");
}
#Modified
public void modify()
{
System.out.println("Stop Test Service onnanogo");
}
private Logger createLogger(final Class<?> clazz)
{
return Logger.getLogger(clazz);
}
#Override
public void logDebug(final Class<?> clazz, final String message)
{
logDebug(clazz, message, null);
}
#Override
public void logDebug(final Class<?> clazz, final String message, final Throwable throwable)
{
final Logger logger = createLogger(clazz);
logger.debug(message, throwable);
}
}
the generated XML is
<?xml version="1.0" encoding="UTF-8"?>
<components xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0">
<scr:component enabled="true" immediate="false" name="Shikashi" activate="start" deactivate="stop" modified="modify">
<implementation class="com.sti.logging.service.LoggingTestService"/>
<service servicefactory="false">
<provide interface="com.sti.loggingservices.serviceinterface.LoggingTestServiceInterface"/>
</service>
</scr:component>
My servlet is
#WebServlet(name = "Wakarimashita", urlPatterns = { "/Wakarimashita"})
#Component
public class Wakarimashita extends HttpServlet
{
private LoggingTestServiceInterface loggingTestServiceInterface;
#Override
protected void doGet(final HttpServletRequest httpServletRequest, final HttpServletResponse httpServletResponse) throws ServletException, IOException
{
// Method just to setup the Servlet to understand how it works
final String language = "language";
final String path = "/sigbud/language/";
if (httpServletRequest.getParameter(language) != null)
{
if (httpServletRequest.getParameter(language).equalsIgnoreCase("Nihongo"))
{
httpServletResponse.sendRedirect(path + "nihongo.jsp");
}
else if (httpServletRequest.getParameter(language).equalsIgnoreCase("Eigo"))
{
httpServletResponse.sendRedirect(path + "eigo.jsp");
}
else if (httpServletRequest.getParameter(language).equalsIgnoreCase("Funansugo"))
{
httpServletResponse.sendRedirect(path + "funansugo.jsp");
}
else
{
httpServletResponse.sendRedirect(path + "unknown.jsp");
}
}
else
{
super.doGet(httpServletRequest, httpServletResponse);
}
loggingTestServiceInterface.logError(getClass(), "Wakarimasen");
}
#Reference(service = LoggingTestServiceInterface.class, cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.DYNAMIC)
public void bindLoggingTestServiceInterface(final LoggingTestServiceInterface loggingTestServiceInterface)
{
this.loggingTestServiceInterface = loggingTestServiceInterface;
}
public void unbindLoggingTestServiceInterface(final LoggingTestServiceInterface loggingTestServiceInterface)
{
if (this.loggingTestServiceInterface.equals(loggingTestServiceInterface))
{
this.loggingTestServiceInterface = null;
}
}
#Activate
public void start(final BundleContext bundleContext)
{
System.out.println("StartTest Service Taisho");
}
#Deactivate
public void stop()
{
System.out.println("Stop Test Service Fukutaisho");
}
#Modified
public void modify()
{
System.out.println("Stop Test Service san jyû kyû");
}
}
the Generated XML
<?xml version="1.0" encoding="UTF-8"?>
<components xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0">
<scr:component name="com.sti.sigbud.servlet.Wakarimashita" activate="start" deactivate="stop" modified="modify">
<implementation class="com.sti.sigbud.servlet.Wakarimashita"/>
<reference name="LoggingTestServiceInterface" interface="com.sti.loggingservices.serviceinterface.LoggingTestServiceInterface" cardinality="1..1" policy="dynamic" bind="bindLoggingTestServiceInterface" unbind="unbindLoggingTestServiceInterface"/>
</scr:component>
Also I tried, but no luck because my servlet doesn't seem to be found (Error 404 - The requested resource () is not available.), to do as Peter Kriens wrote there : How to consume OSGi service from OSGi HTTP Service
So I modified my servlet like so :
#Component(service = Servlet.class, property = {"alias=/Wakarimashita"})
public class Wakarimashita extends HttpServlet
The generated XML is
<?xml version="1.0" encoding="UTF-8"?>
<components xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0">
<scr:component name="com.sti.sigbud.servlet.Wakarimashita" activate="start" deactivate="stop" modified="modify">
<implementation class="com.sti.sigbud.servlet.Wakarimashita"/>
<service servicefactory="false">
<provide interface="javax.servlet.Servlet"/>
</service>
<property name="alias" value="/Wakarimashita"/>
<reference name="LoggingTestServiceInterface" interface="com.sti.loggingservices.serviceinterface.LoggingTestServiceInterface" cardinality="1..1" policy="dynamic" bind="bindLoggingTestServiceInterface" unbind="unbindLoggingTestServiceInterface"/>
</scr:component>
I access the servlet from my JSP
<form action="Wakarimashita" method="GET">
<input type="text" name="language" size="50"/>
<input type="submit" value="Submit" />
</form>
To test the above I have in my deployed bundles org.apache.felix.http.api-2.2.1, org.apache.felix.http.whiteboard-2.2.1 just as in the post. Didn't find if there is a switch to put on.
Also I checked with org.apache.felix.webconsole-4.2.0-all the bundles, and the service is there up and running, it says that my consumer bundle is using it.
You have two parties creating instances of your servlet. Once is DS and the other is the web container. You cannot have 2 masters. The web container basically has to be in charge since it will only send requests to the instance of your servlet that it creates.
If there was an implementation that supported both web container and DS, then you would be set. But I have never heard of such a thing.
I don't know if Glassfish supports the OSGi Web Application Specification (Ch 128). If it does, then you can interact with the OSGi service layer as described in 128.6.
This is my applicationContext.xml
<bean id="JdbcUserDao" class="controller.User.JdbcUserDao">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
p:driverClassName="org.apache.derby.jdbc.ClientDriver"
p:url="jdbc:derby://localhost:1527/TodoDb"
p:username="root"
p:password="root" />
This is my implDao class :
#Repository
public class JdbcUserDao implements IUserDao {
private JdbcTemplate jt;
#Autowired
private DataSource dataSource;
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
jt = new JdbcTemplate(this.dataSource);
}
public JdbcTemplate getJt() {
return jt;
}
public void setJt(JdbcTemplate jt) {
this.jt = jt;
}
#Override
public List<User> getUsers(final String username, final String password) {
List<User> users = this.jt.query("SELECT username, password FROM USERS",
new RowMapper<User>() {
#Override
public User mapRow(ResultSet rs, int i) throws SQLException {
User user = new User();
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
return user;
}
});
return users;
}
}
Problems:
this.dataSource available when it sets the dataSource through #Autowired like the configs in xml
when I use dataSource in getUsers, it become null ?
Questions:
How can I get this works ?
I'm new to spring3 so I really need your help.
In order to use autowiring, you need to add the following to your xml file configuration.
<context:annotation-config />
If it doesn't help then please add
<context:component-scan base-package="org.springframework.jdbc.datasource" />
Try adding the AutowiredPostProcessor to the config
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor">
</bean>
You could try adding the autowire to the set method instead of the property.
you need to import the class which you are doing autowired without access modifiers in repository class file
com.<your project>.controller.User.JdbcUserDao
and spring annotation
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.repository.CrudRepository;
#Repository
public class JdbcUserDao implements IUserDao {
#Autowired
DataSource dataSource;