How to convert XML to String with JAXB and spring-boot? - spring

When I run a mvn spring-boot:run on the folder that has the pom.xml file the application starts and serializes a POJO into a XML correctly, but when I do it by going to the target folder and starting it by using java -jar in the jar file I get javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath caused by .java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory.
In my maven I have the following JAXB dependencies:
<!-- JAXB API -->
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
</dependency>
<!-- JAXB Runtime -->
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.5</version>
<scope>runtime</scope>
</dependency>
Here's the code that serializes a POJO into XML:
private static final Pattern REMOVE_HEADER = Pattern.compile("\\<\\?xml(.+?)\\?\\>");
public static <T> String toXML(final T data) {
try {
final var jaxbMarshaller = JAXBContext.newInstance(data.getClass()).createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
final var sw = new StringWriter();
jaxbMarshaller.marshal(data, sw);
return XMLUtils.REMOVE_HEADER.matcher(sw.toString()).replaceAll("").strip();
} catch (final JAXBException e) {
XMLUtils.LOGGER.error("Error while converting POJO to XML. ERROR: {}.", e.getMessage(), e);
}
return "";
}
Here's the log when I start the application with java -jar:
2021-12-26 21:19:14,526 [ForkJoinPool.commonPool-worker-11] ERROR com.enterprise.system.shared.util.XMLUtils - Error while converting POJO to XML. ERROR: Implementation of JAXB-API has not been found on module path or classpath..
javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath.
- with linked exception:
[java.lang.ClassNotFoundException: com.sun.xml.bind.v2.ContextFactory]
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:232)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:375)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:691)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:632)
at com.enterprise.system.shared.util.XMLUtils.toXML(XMLUtils.java:26)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:720)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ReduceOps$ReduceTask.doLeaf(ReduceOps.java:952)
at java.base/java.util.stream.ReduceOps$ReduceTask.doLeaf(ReduceOps.java:926)
at java.base/java.util.stream.AbstractTask.compute(AbstractTask.java:327)
at java.base/java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:746)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)
Caused by: java.lang.ClassNotFoundException: com.sun.xml.bind.v2.ContextFactory
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
at javax.xml.bind.ServiceLoaderUtil.nullSafeLoadClass(ServiceLoaderUtil.java:92)
at javax.xml.bind.ServiceLoaderUtil.safeLoadClass(ServiceLoaderUtil.java:125)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:230)
... 17 more
Here's an image of the generated spring-boot fat jar with the JAXB dependencies:
Here's my dependency tree:
--- maven-dependency-plugin:3.2.0:tree (default-cli) # java-eleven-jaxb-hell ---
com.enterprise.system:java-eleven-jaxb-hell:jar:0.0.1-SNAPSHOT
+- org.slf4j:slf4j-log4j12:jar:1.7.32:compile (optional)
| +- org.slf4j:slf4j-api:jar:1.7.32:compile (optional)
| \- log4j:log4j:jar:1.2.17:compile (optional)
+- org.springframework.boot:spring-boot-autoconfigure:jar:2.6.2:compile
| \- org.springframework.boot:spring-boot:jar:2.6.2:compile
| +- org.springframework:spring-core:jar:5.3.14:compile
| | \- org.springframework:spring-jcl:jar:5.3.14:compile
| \- org.springframework:spring-context:jar:5.3.14:compile
| +- org.springframework:spring-aop:jar:5.3.14:compile
| +- org.springframework:spring-beans:jar:5.3.14:compile
| \- org.springframework:spring-expression:jar:5.3.14:compile
+- org.projectlombok:lombok:jar:1.18.22:provided
+- jakarta.xml.bind:jakarta.xml.bind-api:jar:2.3.3:compile
| \- jakarta.activation:jakarta.activation-api:jar:1.2.2:compile
\- com.sun.xml.bind:jaxb-impl:jar:2.3.5:runtime
\- com.sun.activation:jakarta.activation:jar:1.2.2:runtime
And finally, here are my model classes:
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
#XmlRootElement(name = "finans")
#XmlAccessorType(XmlAccessType.FIELD)
#Data
#NoArgsConstructor
#AllArgsConstructor
public class FinanTokenDTO {
#XmlAttribute
private String pln;
#XmlAttribute
private String ope;
#XmlAttribute
private String mod;
#XmlAttribute
private String mis;
#XmlAttribute
private String val;
#XmlAttribute
private String car;
#XmlAttribute
private String dti;
#XmlAttribute
private String dtf;
#XmlAttribute
private String ota;
#XmlElement
private FinanDTO finan;
}
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
#XmlRootElement(name = "finan")
#XmlAccessorType(XmlAccessType.FIELD)
#Data
#NoArgsConstructor
#AllArgsConstructor
public class FinanDTO {
#XmlAttribute
private String prd;
#XmlAttribute
private String pkg;
#XmlAttribute
private String val;
#XmlAttribute
private String fty;
}
I am using java 11 and I am aware that in java 11 JAXB was removed from the SE JDK because it is considered as a EE feature.
I am not able to execute it using mvn spring-boot:run in production environment because of the size of the docker image and security related issues using docker container.
Since Spring Boot generates a fat jar, shouldn't the application run with java -jar applied to the spring boot fat jar generated file the same way as it does with mvn spring-boot:run inside the folder with pom.xml?
EDIT:
After a lot of digging and testing I found that the problem occurs when we try to marshall several valid POJOs using parallel stream instead of stream on the POJOs list. I uploaded the code in java-eleven-jaxb-hell to better understanding, unfortunatelly I cannot change parallelStream to stream because of performance issues. Just to remember, for the problem to happen you have to run java -jar against spring-boot generated fat jar in target folder.

Try adding the next dependency:
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>2.3.1</version>
</dependency>

I suggest you to replace the JAXB-impl from Sun by the one from Glassfish:
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.5</version>
</dependency>
Generally speaking, Sun does not exists anymore since years, and the package might be there only for compatibility. The recommended JAXB implementation today comes from Glassfish.

Related

Spring Data JDBC + Querydsl: error "JdbcRepositoryFactory does not support Querydsl"

I want to use Spring Data JDBC with QueryDSL support. According to Spring documentation (https://docs.spring.io/spring-data/jdbc/docs/current/reference/html/#core.extensions.querydsl) it is supported, but I couldn't make it working.
I use MariaDB as database and my version of SpringBoot is 2.6.0.
My dependencies in pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-sql-spring</artifactId>
</dependency>
Configuration:
#Configuration
#EnableJdbcRepositories
#EnableTransactionManagement
public class DBConfig {
}
My entity class:
package com.test.model.metadata;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
#Table
public class Action {
#Id
private long id;
private String name;
...
}
My repository class:
package com.test.repository;
import java.util.List;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;
import com.test.model.Action;
import com.querydsl.core.types.Predicate;
#Repository
public interface ActionRepository extends PagingAndSortingRepository<Action, Long>, QuerydslPredicateExecutor<Action> {
#Override
List<Action> findAll(Predicate predicate);
}
QueryDSL predicate usage:
QAction action = QAction.action;
Predicate predicate = action.name.like("%Accept%");
List<Action> actions = actionRepository.findAll(predicate);
Q-classes are generated properly by preprocessor, compilation suceeds but during application startup I am getting error:
org.springframework.data.repository.core.support.UnsupportedFragmentException: Repository com.atende.db.metadata.jdbcrepository.ActionRepository implements org.springframework.data.querydsl.QuerydslPredicateExecutor but JdbcRepositoryFactory does not support Querydsl!
What yet could be missing in my solution?
When I am using QueryDSL directly with JdbcTemplate it works:
QAction action = QAction.action;
SQLTemplates dialect = new MySQLTemplates();
Connection connection = DataSourceUtils.getConnection(jdbcTemplate.getDataSource());
SQLQuery<String> query = new SQLQuery<>(connection, dialect);
List<Tuple> actions = query.select(action.id, action.name)
.from(action)
.where(action.name.like("%Action%"))
.fetch();
I also tried to use infobip querydsl library (https://github.com/infobip/infobip-spring-data-querydsl) but got the same error.
This is a misinterpretation of the documentation (not your fault, it is structured in an unfortunate way).
You are looking at the preface which describes the general way to work with Spring Data modules.
This does not indicate that the module at hand (JDBC in this case) supports all the features mentioned.
Spring Data JDBC does not provide Querydsl support.
That means that the #EnableJdbcRepositories which activates spring-data-jdbc repository implementation does not provide Querydsl support.
If you have infobip-spring-data-jdbc-querydsl-boot-starter on classpath and remove #EnableJdbcRepositories it should work.
QuerydslJdbcPredicateExecutor is the fragment implementation.

Spring Cucumber ActiveProfiles annotation not working with CucumberContext

I'm working on a project where we have a component which consists:
core
connector to external system 1
connector to external system 2
The connectors are mutually exlusive (if connector1 is active, connector2 is always inactive and vice versa). The core and a single connector are autowired on startup of the ApplicationContext. Which connector is instantiated is based on a value in the spring application properties.
We're writing integration tests using spring-cucumber (v6.2.2). For each external system, I want to run a set of cucumber tests. I've created 2 testsets using annotations on the cucumber scenario's which allows me to seperate the tests for connector1 and connector2.
The problem I'm having is that I need both testsets to run with a different spring profile, so I can use a different configuration. I can't find how to do this.
Current implementation (with a single profile):
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>6.2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>6.2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-spring</artifactId>
<version>6.2.2</version>
<scope>test</scope>
</dependency>
CucumberConnector1IT.java
package omitted.for.company.rules;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
#RunWith(Cucumber.class)
#CucumberOptions(
features = { "classpath:feature/" },
glue = { "omitted.for.company.rules.cucumber.step" },
plugin = { "pretty", "json:target/cucumber-report/cucumber.json",
"html:target/cucumber-report/cucumber.html" },
tags = "#Connector1 and not #ignore" // tags make sure only applicable tests are run
)
public class CucumberConnector1IT {
}
CucumberConnector2IT.java
package omitted.for.company.rules;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
#RunWith(Cucumber.class)
#CucumberOptions(
features = { "classpath:feature/" },
glue = { "omitted.for.company.rules.cucumber.step" },
plugin = { "pretty", "json:target/cucumber-report/cucumber.json",
"html:target/cucumber-report/cucumber.html" },
tags = "#Connector2 and not #ignore" // tags make sure only applicable tests are run
)
public class CucumberConnector2IT {
}
StepInitializer.java
package omitted.for.company.rules.steps;
import io.cucumber.java.Before;
import io.cucumber.spring.CucumberContextConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;
#SpringBootTest
#ActiveProfiles("test") // I can only get this to work if the #ActiveProfiles and #CucumberContextConfiguration annotations are on the same class
#CucumberContextConfiguration
public class StepInitializer {
// mock some beans to use in cucumber test
#MockBean
private EventProducer eventProducer;
#MockBean
private RestInterface restInterface;
#Before
public void setup() {
}
}
So far everything works. But what I need now is to put the #ActiveProfiles() annotation on a different class than the #CucumberContextConfiguration. If I can do this then I can annotate the correct step classes with the required profiles.
Problem is that I don't understand the spring annotations well enough to know which ones I can move and which ones I cannot. I found this example of exactly what I'm trying to do (spring-cucumber-profiles repo, notice the location of the #ActiveProfiles annotation here) . Unfortunately, it uses an older version of cucumber-spring (v5.6.0). That version doesn't yet have the #CucumberContextConfiguration annotation and does some magic with the spring context according to the documentation (Release notes of cucumber-spring). I tried to checkout the example repo and upgrade it to v6.2.2 but couldn't get it working with the new version.
If anyone spots what I'm doing wrong in my own examples, or has the possibility to get the example repo working with version 6.2.2 of cucumber-spring that would be much appreciated.
Thanks in advance! :)
I've solved the issue by separating the packages a bit, and creating separate StepInitializer classes for both testsets.
Current setup:
Test runner:
package omitted.for.company.rules;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
#RunWith(Cucumber.class)
#CucumberOptions(
features = { "classpath:feature/" },
extraGlue = { "omitted.for.company.rules.cucumber.step.common" }, // used extraGlue instead of glue
plugin = { "pretty", "json:target/cucumber-report/cucumber.json",
"html:target/cucumber-report/cucumber.html" },
tags = "#Connector1 and not #ignore" // tags make sure only applicable tests are run
)
public class CucumberConnector1IT {
}
Context Configuration:
package omitted.for.company.rules.steps;
import io.cucumber.java.Before;
import io.cucumber.spring.CucumberContextConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;
#SpringBootTest
#ActiveProfiles({ "test", "test-connector1" })
#CucumberContextConfiguration
public class Connector1StepInitializer {
// mock some beans to use in cucumber test
#MockBean
private EventProducer eventProducer;
#MockBean
private RestInterface restInterface;
#Autowired
private ApplicationContext applicationContext;
#Autowired
private Environment environment;
#Before
public void setup() {
assertThat(applicationContext).isNotNull();
assertThat(environment.getActiveProfiles()).containsOnly("test","test-connector1");
}
}
Both connectors/test runners have their own runner class and their own ContextConfiguration class.
It's very important that the classes containing the #CucumberContextConfiguration annotation are not in the shared glue package (as provided in the extraGlue property in the #CucumberOptions annotation).
Package structure looks like this:
├───common
│ └───step // Contains shared steps. This path should be in the 'extraGlue' field of the runner classes
├───connector1
│ │ CucumberConnector1IT.java // Runner 1
│ └───step
│ Connector1Steps.java // Specific steps
│ Connector1StepInitializer.java // has #ActiveProfiles and #CucumberContextConfiguration annotations, use to mock beans
└───connector2
│ CucumberConnector1IT.java // Runner 2
└───step
Connector2Steps.java // Specific steps
Connector2StepInitializer.java // has #ActiveProfiles and #CucumberContextConfiguration annotations, use to mock beans
This way I can still use different spring profiles :).

How I can resolve this problem (Class<SpringJUnit4ClassRunner> cannot be resolved to a type)?

I realized a simple projetc using spring and maven, my project contains an interface and 3 classes and the pom.xml file
Interface : CompactDisc.java
3 classes :
SgtPeppers.java that implements the CompactDisc interface
CDPlayersConfig.java is an empty class and contains the annotations of automatic scan
CDPlayersTest.java is a test class to test if the spring container works.
My problem is with #RunWith(SpringJUnit4ClassRunner.class) and #ContextConfiguration(classes=CDPlayersConfig.class), Eclipse suggests this proposition for the first annotation Class cannot be resolved to a type and it doesn't understand the second annotation.
You find here the code :
CompactDisc.java
package soundsystem;
public interface CompactDisc {
void play();
}
SgtPeppers.java
package soundsystem;
import org.springframework.stereotype.Component;
#Component
public class SgtPeppers implements CompactDisc{
private String title = "Sgt. Pepper's Lonely Hearts Club Band";
private String artist = "The Beatles";
public void play() {
System.out.println("Playing " + title + "by"+ artist);
}
}
CDPlayersConfig.java
package soundsystem;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
#Configuration
#ComponentScan
public class CDPlayersConfig {
}
CDPlayerTest.java
package soundsystem;
import static org.junit.Assert.assertNotNull;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.jta.SpringJtaSynchronizationAdapter;
#RunWith(SpringJUnit4ClassRunner.class)//Here is my problem
#ContextConfiguration(classes=CDPlayersConfig.class)//Here is my problem
public class CDPlayerTest {
#Autowired
private CompactDisc cd;
#Test
public void cdShouldNotBeNull() {
assertNotNull(cd);
}
}
Dependencies im the pom file
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.0.5.RELEASE</version>
<scope>test</scope>
</dependency>
In Eclipse
Right Click on your Project
Select Maven
Select Update Project
Tick
Update project config from pom.xml
Refresh workspace
Clean projects
After doing that the required libraries should be available to Eclipse and you should be able to import the classes as required.
I can't see
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.ContextConfiguration;
in your import section. Also, maybe you should use SpringRunner.class instead of SpringJUnit4ClassRunner.class
Control+click on the class. Eclipse will open the file. Copy the package name. Create a new import statement and paste the package name + the class name. Problem solved.
If Eclipse does not open the file when you control+click, you don't have it on your class path or imported correctly.
You are missing the imports (import org.springframework...) for SpringJUnit4ClassRunner and ContextConfiguration. That's why they are not recognized.
You have to add dependency:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.9.RELEASE</version>
</dependency>
And then
import org.springframework.test.context.ContextConfiguration;
It's working in my Gradle project after complete some steps.
1st: Add dependency in build.gradle file ->
testImplementation 'junit:junit:4.13.2'
implementation 'org.springframework:spring-test:4.0.0.RELEASE'
2nd: Clean Gradle project using IDE or using command prompt -> Open command prompt -> Go to project location c:\gradle_projects\test_gradle>gradlew clean build -> Enter
3rd: Refresh Gradle project -> Open command prompt -> Go to project location c:\gradle_projects\test_gradle>gradlew --refresh-dependencies -> Enter
4th: Go to IDE -> right-click on project name -> Gradle -> Refresh Gradle Project
-> finally download jar files and import class

Injecting SoyTemplateRenderer in custom Atlassian JIRA plugin

I'm currently trying to develop a custom Jira plugin, which also uses a servlet to render a Soy template.
This is the code of my servlet:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package at.fraiss.plugins.custommenuitem.servlets;
import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import com.atlassian.soy.renderer.SoyTemplateRenderer;
import java.util.HashMap;
import java.util.Map;
/**
*
* #author Mario
*/
public class SoyTemplateServlet extends HttpServlet {
private SoyTemplateRenderer soyTemplateRenderer;
public SoyTemplateServlet(SoyTemplateRenderer soyTemplateRenderer)
{
this.soyTemplateRenderer = soyTemplateRenderer;
}
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
response.setContentType("text/html");
response.getWriter().write(getHtml());
}
public String getHtml()
{
Map<String, Object> data = new HashMap<String,Object>();
data.put("isLocal", true);
data.put("url", "http://www.example.com");
data.put("title", "example");
return this.soyTemplateRenderer.render("jira.webresources:soy-templates", "JIRA.Templates.Links.helpLink", data);
}
}
This is how I defined the soy template files inside the atlassian-plugin.xml descriptor:
<web-resource key="soy-templates">
<dependency>com.atlassian.soy.soy-template-plugin:soy-deps</dependency>
<!-- Available to the server-side only -->
<resource type="soy" name="links" location="links.soy"/>
 
<!-- Make available to the client-side in JS as well... -->
<transformation extension="soy">
<transformer key="soyTransformer"/>
</transformation>
<resource type="download" name="Links.soy.js" location="links.soy"/>
</web-resource>
I have added the following section to my pom.xml:
<dependency>
<groupId>com.atlassian.soy</groupId>
<artifactId>soy-template-renderer-api</artifactId>
<version>4.0.4</version>
<scope>provided</scope>
</dependency>
and always get this error when try to acces the servlet
[INFO] [talledLocalContainer] Caused by: org.springframework.beans.factory.Unsat isfiedDependencyException: Error creating bean with name 'at.fraiss.plugins.cust ommenuitem.servlets.SoyTemplateServlet': Unsatisfied dependency expressed throug h constructor argument with index 0 of type [com.atlassian.soy.renderer.SoyTempl ateRenderer]: : No qualifying bean of type [com.atlassian.soy.renderer.SoyTempla teRenderer] found for dependency: expected at least 1 bean which qualifies as au towire candidate for this dependency. Dependency annotations: {}; nested excepti on is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualif ying bean of type [com.atlassian.soy.renderer.SoyTemplateRenderer] found for dep endency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {} [INFO] [talledLocalContainer] at org.springframework.beans.factory.support.Con structorResolver.createArgumentArray(ConstructorResolver.java:749) [INFO] [talledLocalContainer] at org.springframework.beans.factory.support.Con structorResolver.autowireConstructor(ConstructorResolver.java:185) [INFO] [talledLocalContainer] at org.springframework.beans.factory.support.Abs tractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanF actory.java:1139) [INFO] [talledLocalContainer] at org.springframework.beans.factory.support.Abs tractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFa ctory.java:1042) [INFO] [talledLocalContainer] at org.springframework.beans.factory.support.Abs tractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory. java:504) [INFO] [talledLocalContainer] at org.springframework.beans.factory.support.Abs tractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.ja va:342) [INFO] [talledLocalContainer] ... 2 filtered [INFO] [talledLocalContainer] at java.lang.reflect.Method.invoke(Method.java:4 97) [INFO] [talledLocalContainer] at com.atlassian.plugin.osgi.spring.DefaultSprin gContainerAccessor.createBean(DefaultSpringContainerAccessor.java:112) [INFO] [talledLocalContainer] at com.atlassian.plugin.module.ClassPrefixModule Factory.createModule(ClassPrefixModuleFactory.java:39) [INFO] [talledLocalContainer] at com.atlassian.plugin.module.PrefixDelegatingM oduleFactory.createModule(PrefixDelegatingModuleFactory.java:100) [INFO] [talledLocalContainer] at com.atlassian.plugin.servlet.descriptors.Serv letModuleDescriptor.getModule(ServletModuleDescriptor.java:48) [INFO] [talledLocalContainer] at com.atlassian.plugin.servlet.DelegatingPlugin Servlet.<init>(DelegatingPluginServlet.java:33) [INFO] [talledLocalContainer] at com.atlassian.plugin.servlet.DefaultServletMo duleManager$LazyLoadedServletReference.create(DefaultServletModuleManager.java:5 41) [INFO] [talledLocalContainer] at com.atlassian.plugin.servlet.DefaultServletMo duleManager$LazyLoadedServletReference.create(DefaultServletModuleManager.java:5 21) [INFO] [talledLocalContainer] at com.atlassian.util.concurrent.LazyReference$S ync.run(LazyReference.java:325) [INFO] [talledLocalContainer] at com.atlassian.util.concurrent.LazyReference.g ...
I also had this problem (and lost hours on it).
The Spring scanner apparently only processes classes marked with #Named.
This worked for me:
#Named("MyServlet")
public class MyServlet extends HttpServlet{
#ComponentImport
private final SoyTemplateRenderer soyTemplateRenderer;
#Inject
public MyServlet(#ComponentImport final SoyTemplateRenderer soyTemplateRenderer) {
this.soyTemplateRenderer = soyTemplateRenderer;
}
}
Apparently this has nothing to do with jiira, but in your frustration you seem to be blaming it and its documentation. It's actually a problem with your use of spring, and your apparent inability to read stack traces.
The first entry in the stack trace mentions, in may different ways, No qualif
ying bean of type [com.atlassian.soy.renderer.SoyTemplateRenderer] found. So, you seem to have not provided a bean definition for the SoyTemplateRenderer for spring to find. Rectify this and this particular problem will disappear.

How to deploy Maven project to Glassfish Server in Intellij Idea 13

I am developing a sample Java EE applicaiton with Intellij Idea 13. Simply, my project is a Maven project and has JPA end EJB modules. But when deploying and running application on Glassfish server I get errors.
I created a Maven project named SimpleEE and added JPA, EJB modules.
Here is my project structure:
|-SampleEE
| |+.idea
| |-src
| | |-main
| | | |-java
| | | | |-beans
| | | | | |-MyBean.java
| | | | |-entities
| | | | |-Staff.java
| | | |-resources
| | | |-META-INF
| | | |-ejb-jar.xml
| | | |-persistence.xml
| | |+test
| |-pom.xml
| |-SampleEE.iml
| |-SampleEE.jpr
|+ExternalLibraries
MyBean.java:
package beans;
import entities.Staff;
import javax.annotation.PostConstruct;
import javax.ejb.LocalBean;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.persistence.EntityManager;
import javax.persistence.Persistence;
#Startup
#LocalBean
#Singleton
public class MyBean {
public MyBean() {
}
#PostConstruct
public void myMain() {
EntityManager em = Persistence.createEntityManagerFactory("mysqlPU").createEntityManager();
em.getTransaction().begin();
Staff staff = new Staff();
staff.setAge(44);
staff.setGender("M");
staff.setSalary(123);
staff.setName("Staff Name");
em.persist(staff);
em.getTransaction().commit();
}
}
Staff.java
package entities;
import javax.persistence.*;
#Entity
public class Staff {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "STAFF_ID")
private int id;
#Column(name = "NAME")
private String name;
#Column(name = "AGE")
private Integer age;
#Column(name = "GENDER")
private String gender;
#Column(name = "SALARY")
private Integer salary;
#Lob
#Column(name = "IMAGE", nullable = true)
private byte[] image;
// Getters and setters
// ...
#Override
public int hashCode() {
// implementation ignored here for simplicity
}
#Override
public boolean equals(Object o) {
// implementation ignored here for simplicity
}
}
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="mysqlPU">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>entities.Staff</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/dbName"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.user" value="mysqlUsername"/>
<property name="javax.persistence.jdbc.password" value="mysqlPassword"/>
</properties>
</persistence-unit>
</persistence>
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>SampleEE</groupId>
<artifactId>SampleEE</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.27</version>
</dependency>
</dependencies>
</project>
I created an EJB Application:Exploded artifact from project structure. In Run/Debug configurations window I built a Glassfish configuration. But when running this configuration, Idea complains that it can not find classes in mysql jdbc driver and shows errors emerging from this error. Server is started but application is not deployed. Error message snippet from Idea output log:
....
[2013-12-13 04:07:31,362] Artifact SampleEE:ejb exploded: Artifact is being deployed, please wait...
[2013-12-13 04:07:33,011] Artifact SampleEE:ejb exploded: Error during artifact deployment. See server log for details.
[2013-12-13 04:07:33,018] Artifact SampleEE:ejb exploded: java.io.IOException: com.sun.enterprise.admin.remote.RemoteFailureException: Error occurred during deployment: Exception while loading the app : javax.ejb.CreateException: Initialization failed for Singleton MyBean. Please see server.log for more details.
Last error in Glassfish log
....
Caused by: Exception [EclipseLink-4003] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException
Exception Description: Configuration error. Class [com.mysql.jdbc.Driver] not found.
....
I guess jar files of libraries are not deployed. But my maven configuration is valid. M2_HOME is set correctly and IDEA resolves maven path. The jar files are also available in local repository.
I created a same structured project in Netbeans and it runs succesfully. I don't know what I am doing wrong or what configuration parameters I am missing.
You need to add a JavaEE module and add create a JavaEE artifact. Then add all libraries you need to that artifact.

Resources