Access a static file saved inside the WEB-INF folder of a Servlet from the doPost() method - image

I'm trying to access some images that I have saved in my Servlet inside the src/main/webapp/WEB-INF/imgs folder, this way:
link
I tryed to access these images with this code within the doPost method of my Servlet:
InputStream s = this.getClass().getClassLoader().getResourceAsStream("http://cardimgs.org/imgs/cardbackground1.jpg");
Movie movie = new Movie();
try {
byte[] bytes = IOUtils.toByteArray(s);
movie.setImage(bytes);
} catch (IOException e) {
e.printStackTrace();
}
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
// Store the image in App Engine's datastore
pm.makePersistent(movie);
} finally {
pm.close();
}
Movie class:
link 2,
the reason why I used the specified urlto create the InputStream is because in my appengine-web.xml I have:
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<application>myApplicationId</application>
<version>1</version>
<threadsafe>true</threadsafe>
<system-properties>
<property name="java.util.logging.config.file" value="WEB-INF/logging.properties" />
</system-properties>
<static-files>
<include path="/**.jpg"/>
<include path="/imgs" >
<http-header name="Access-Control-Allow-Origin" value="http://cardimgs.org" />
</include>
</static-files>
</appengine-web-app>
where I try to define my static files.
My problem is, though, that with the above code I can't access my file and fill the InputStream, which appears to be null, therefore returning a NullPointerException.
How can I successfully access my static files?

ClassLoader.getResourceAsStream() loads resources using *the class loader**. It thus looks for them in the classpath. The classpath of a web-app is constitued from WEB-INF/classes and from all the jars inside WEB-INF/lib. The path it expects looks like com/mycompany/myproject/somefile.txt. It can't be a HTTP URL.
What you need is ServletContext.getResourceAsStream("/WEB-INF/imgs/cardbackground1.jpg"). This method loads a resource from anywhere inside the web-app.

Related

Not Found in ExternalContext as a Resource Error (Amazon Elastic Beanstalk / Spring Boot / JSF + Primefaces)

I created an app using Spring Boot, JSF + Primefaces. I deployed it to Amazon Elastic Beanstalk, and set the environment variables that project needed to use.
When I tried to access my website, I got this error message:
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Thu Mar 04 07:21:33 UTC 2021
There was an unexpected error (type=Not Found, status=404).
/login.xhtml Not Found in ExternalContext as a Resource
Here is my Faces Config (as java class):
package com.jsf;
#SpringBootApplication
#Configuration
#ComponentScan("com.jsf")
public class HelloJsfApplication {
public static void main(String[] args) {
SpringApplication.run(HelloJsfApplication.class, args);
}
// JSF Configration Başlangıc
#Bean
public ServletRegistrationBean<FacesServlet> facesServletRegistraiton() {
ServletRegistrationBean<FacesServlet> registration = new ServletRegistrationBean<FacesServlet>(
new FacesServlet(), new String[] { "*.xhtml" });
registration.setName("Faces Servlet");
registration.setLoadOnStartup(1);
registration.addUrlMappings("*.xhtml");
return registration;
}
#Bean
public ServletContextInitializer servletContextInitializer() {
return servletContext -> {
servletContext.setInitParameter("com.sun.faces.forceLoadConfiguration", Boolean.TRUE.toString());
servletContext.setInitParameter("primefaces.THEME", "bootstrap");
// Primefaces client browser tarafında kontrol edilebilme örneğin textbox 10
// karakter olmalı vs..
servletContext.setInitParameter("primefaces.CLIENT_SIDE_VALIDATION", Boolean.TRUE.toString());
// Xhtml sayfalarında commentlerin parse edilmemesi.
servletContext.setInitParameter("javax.faces.FACELETS_SKIP_COMMENTS", Boolean.TRUE.toString());
// primefaces icon set için
servletContext.setInitParameter("primefaces.FONT_AWESOME", Boolean.TRUE.toString());
};
}
#Bean
public ServletListenerRegistrationBean<ConfigureListener> jsfConfigureListener() {
return new ServletListenerRegistrationBean<ConfigureListener>(new ConfigureListener());
}
// JSF Configration Sonu
}
my faces config file under webapp/WEB-INF folder:
<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
version="2.2">
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
</faces-config>
and as you see, all my xhtml files are under webapp folder:
my application.properties file (using java params):
server.servlet.context-path = ${CONTEXT_PATH}
server.port = ${PORT}
spring.datasource.url = ${SPRING_DATASOURCE_URL}
spring.datasource.username = ${SPRING_DATASOURCE_USERNAME}
spring.datasource.password = ${SPRING_DATASOURCE_PASSWORD}
spring.jpa.properties.hibernate.dialect = ${SPRING_JPA_DATABASE_PLATFORM}
# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = ${SPRING_JPA_HIBERNATE_DDL_AUTO}
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=${SPRING_JPA_HIBERNATE_LOB_CREATION}
spring.datasource.driver-class-name=${SPRING_DATASOURCE_DRIVERCLASSNAME}
and here are java parameters that I defined on Amazon (I will not post db params for security reasons):
PORT=5000
CONTEXT_PATH=/
SPRING_DATASOURCE_DRIVERCLASSNAME=org.postgresql.Driver
...
and so on.
Really I run out of solutions. With same packaged jar, I deployed to Heroku with same environment parameters, and it works flawlessly.
Where I am doing wrong with Amazon Elastic Beanstalk?
Kind regards.
I found the problem.
Maven, does not add *.xhtml files inside "jar" package.
Here is the ss of decompiled version of jar packaging (with jd-gui)
..and here is the ss of war packaging:
so if you are think that you did everything correct during development and managing after, check the packaging type.

How to declare a element for complex data type defined in a xsd file located in jar file

I have a below xsd file in a jar dependency file in a Spring boot project. The xsd does not declare the element declaration, which is required by spring boot validation. So I am trying to add another xsd in my project resource folder to declare element type.
XSD in Jar file: /wsdl/xsd/UserService-v1-0.xsd
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema targetNamespace="http://usermanagement.com/userservice/xsd/2014/07"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:userservice="http://usermanagement.com/userservice/xsd/2014/07"
elementFormDefault="qualified">
<xsd:import namespace="http://usermanagement.com/userservice/common/xsd/2014/09" schemaLocation="userserviceCommon-v1-0.xsd"/>
<xsd:import namespace="http://usermanagement.com/userserviceabsolute/common/xsd/2014/09" schemaLocation="userserviceAbsoluteCommon-v1-0.xsd"/>
<xsd:complexType name="GetUsersRequest">
<xsd:attribute name="language" type="xsd:language" use="optional" default="en" />
</xsd:complexType>
</xsd:schema>
Please note that I tried to keep the complex type simple by removing some of the elements for this post. The location of file is /wsdl/xsd.
XSD to declare the element in the main Project resource: /wsdl/xsd/UserService-type-v1-0.xsd
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema targetNamespace="http://usermanagement.com/userservice/wsdl/userserviceService-v1-0"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:userservice="http://usermanagement.com/userservice/xsd/2014/07"
elementFormDefault="qualified">
<import namespace="http://usermanagement.com/userservice/xsd/2014/07" schemaLocation="jar:file://{path to the jar}/!/wsdl/xsd/userserviceService-v1-0.xsd"/>
<element name="GetUsersRequest" type="userservice:GetUsersRequest"/>
</xsd:schema>
As per my understanding we need to refer to the schemaLocation of xsd file in jar using notation "jar:file://{path to the jar}/!/wsdl/xsd/userserviceService-v1-0.xsd".
However I am not sure how to declare the path to the jar. Also not sure if this is the only way to refer to the definitions in the xsd in the jar files. In the above approach when ever a new version of jar is released we need to update the xsd file.
Also including the Spring WS schema validation config:
#Configuration
public class MyWsValidatorConfig extends WsConfigurerAdapter {
#Override
public void addInterceptors(List<EndpointInterceptor> interceptors) {
PayloadValidatingInterceptor validatingInterceptor = new PayloadValidatingInterceptor();
validatingInterceptor.setValidateRequest(true);
validatingInterceptor.setValidateResponse(true);
validatingInterceptor.setXsdSchemaCollection(new XsdSchemaCollection() {
#Override
public XsdSchema[] getXsdSchemas() {
return null;
}
#Override
public XmlValidator createValidator() {
try {
return XmlValidatorFactory.createValidator(getSchemas(), "http://www.w3.org/2001/XMLSchema");
} catch (Exception e) {
log.error("Failed to create validator e={}", e);
}
return null;
}
public Resource[] getSchemas() {
List<Resource> schemaResources = new ArrayList<>();
schemaResources.add(new ClassPathResource("/wsdl/xsd/UserService-v1-0.xsd"));
schemaResources.add(new ClassPathResource("/wsdl/xsd/UserService-type-v1-0.xsd"));
return schemaResources.toArray(new Resource[schemaResources.size()]);
}
});
interceptors.add(validatingInterceptor);
}
}
This is the first time I am working with XSD and SOAP web services. Able to cross other hurdles but got stuck with this issue.
Please help.

Mybatis - Invalid bound statement (not found)

I have created a new project using mybatis to connect to a mysql database. This is my second project using mybatis so I am familiar with it but am getting the following error when I call the save method:
2019-03-05 10:08:01.031 ERROR 86438 --- [nio-9905-exec-1] c.q.f.r.c.ResolveRestController : Error starting preset: Invalid bound statement (not found): com.qlsdistribution.fps.resolverender.data.mybatis.mapper.ResolveJobReportMapper.saveResolveJobReport
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.qlsdistribution.fps.resolverender.data.mybatis.mapper.ResolveJobReportMapper.saveResolveJobReport
at org.apache.ibatis.binding.MapperMethod$SqlCommand.(MapperMethod.java:232) ~[mybatis-3.5.0.jar:3.5.0]
at org.apache.ibatis.binding.MapperMethod.(MapperMethod.java:50) ~[mybatis-3.5.0.jar:3.5.0]
at org.apache.ibatis.binding.MapperProxy.lambda$cachedMapperMethod$0(MapperProxy.java:62) ~[mybatis-3.5.0.jar:3.5.0]
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660) ~[na:1.8.0_101]
at org.apache.ibatis.binding.MapperProxy.cachedMapperMethod(MapperProxy.java:62) ~[mybatis-3.5.0.jar:3.5.0]
.....
My mybatis config file is as follows (in src/main/resources):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!-- changes from the defaults -->
<setting name="lazyLoadingEnabled" value="true" />
<!-- Mybatis logging -->
<setting name="logImpl" value="LOG4J2"/>
</settings>
<typeAliases>
<package name="com.qlsdistribution.fps.resolverender.data.mybatis.domain"/>
</typeAliases>
<mappers>
<mapper resource="mapper/ResolveJobReport.xml"/>
<!-- <mapper resource="com/qlsdistribution/fps/resolverender/data/mybatis/mapper/ResolveJobReport.xml"/> -->
</mappers>
</configuration>
As you can see I have tried different locations for the mapper xml file but if I put invalid syntax in the mapper xml file, it fails with invalid syntax (SAXParseException) instead so I know the mapper xml file is being read.
The mapper xml file is as follows (in src/main/resources/mapper):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qlsdistribution.fps.resolverender.data.mybatis.ResolveJobReportMapper">
<resultMap id="resolveJobReport" type="com.qlsdistribution.fps.resolverender.data.mybatis.domain.ResolveJobReport">
<result property="id" column="id" />
<result property="fpsProjectName" column="fps_project_name" />
<result property="inputPath" column="input_path" />
<result property="destinationPath" column="destination_path" />
<result property="presetName" column="preset_name" />
<result property="ipAddress" column="ip_address" />
<result property="frameRate" column="frame_rate" />
<result property="resolveProjectName" column="resolve_project_name" />
<result property="width" column="width" />
<result property="height" column="height" />
<result property="renderFormat" column="render_format" />
<result property="renderCodec" column="render_codec" />
<result property="scriptPath" column="script_path" />
<result property="cliOutput" column="cli_output" />
<result property="jobStartedDate" column="job_started_date" />
<result property="jobFinishedDate" column="job_finished_date" />
<result property="createdBy" column="created_by" />
<result property="createdDate" column="created_date" />
<result property="modifiedBy" column="modified_by" />
<result property="modifiedDate" column="modified_date" />
</resultMap>
<select id="getAllResolveJobReports" resultMap="resolveJobReport">
SELECT id, fps_project_name, input_path, destination_path, preset_name, ip_address, frame_rate, resolve_project_name, width, height,
render_format, render_codec, script_path, cli_output, job_started_date, job_finished_date, created_by, created_date, modified_by, modified_date
FROM resolve_job_report
WHERE fps_setting_id = #{value}
ORDER by id desc;
</select>
<select id="getAllResolveJobReportsById" parameterType="Long" resultMap="resolveJobReport">
SELECT id, fps_project_name, input_path, destination_path, preset_name, ip_address, frame_rate, resolve_project_name, width, height,
render_format, render_codec, script_path, cli_output, job_started_date, job_finished_date, created_by, created_date, modified_by, modified_date
FROM resolve_job_report
WHERE id = #{value};
</select>
<insert id="saveResolveJobReport" parameterType="com.qlsdistribution.fps.resolverender.data.mybatis.domain.ResolveJobReport">
INSERT INTO resolve_job_report
(fps_project_name, input_path, destination_path, preset_name, ip_address, frame_rate, resolve_project_name, width, height,
render_format, render_codec, script_path, cli_output, job_started_date, job_finished_date, created_by)
VALUE
(#{fpsProjectName},#{inputPath},#{destinationPath},#{presetName},#{ipAddress},#{frameRate},#{resolveProjectName},#{width},#{height},
#{renderFormat},#{renderCodec}, #{scriptPath},#{cliOutput},#{jobStartedDate},#{jobFinishedDate},#{createdBy});
</insert>
<update id="updateResolveJobReportById" parameterType="resolveJobReport">
UPDATE resolve_job_report
SET
fps_project_name = #{fpsProjectName},
input_path = #{inputPath},
destination_path = #{destinationPath},
preset_name = #{presetName},
ip_address = #{ipAddress},
frame_rate = #{frameRate},
resolve_project_name = #{resolveProjectName},
width = #{width},
height = #{height},
render_format = #{renderFormat},
render_codec = #{renderCodec},
script_path = #{scriptPath},
cli_output = #{cliOutput},
job_started_date = #{jobStartedDate},
job_finished_date = #{jobFinishedDate},
modified_by = #{modifiedBy}
where id = #{id};
</update>
<delete id="deleteResolveJobReporttById" parameterType="Long">
DELETE FROM resolve_job_report
WHERE id = #{value}
</delete>
</mapper>
My application.properties file contains the following (in (src/main/resources):
spring.datasource.url=jdbc:mysql://localhost:3306/fpsresolvetool?createDatabaseIfNotExist=true&autoReconnect=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.schema=classpath:schema.sql
mybatis.config-location=classpath:SqlMapConfig.xml
I have even tried using the latest mybatis versions in my pom.xml:
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
My spring boot application is as follows:
#SpringBootApplication
#EnableScheduling
#ComponentScan({"com.qlsdistribution.fps.resolverender"})
#EnableJms
#MapperScan("com.qlsdistribution.fps.resolverender.data.mybatis")
public class FPSResolveRenderApp implements WebMvcConfigurer {
/** UTF-8 Character set name */
private static final String UTF_8 = "UTF-8";
/** Logger */
private static final Logger logger = LogManager.getLogger(FPSResolveRenderApp.class);
public static void main(String[] args) {
new SpringApplicationBuilder(FPSResolveRenderApp.class).run(args);
}
/**
* Creates and gets the FilterRegistrationBean
* #return
*/
#Bean
public FilterRegistrationBean<CharacterEncodingFilter> filterRegistrationBean() {
FilterRegistrationBean<CharacterEncodingFilter> registrationBean = new FilterRegistrationBean<CharacterEncodingFilter>();
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding(UTF_8);
registrationBean.setFilter(characterEncodingFilter);
return registrationBean;
}
}
The mapper interface is as follows:
#Mapper
public interface ResolveJobReportMapper {
public List<ResolveJobReport> getAllResolveJobReports();
public List<ResolveJobReport> getAllResolveJobReports(RowBounds rowBounds);
public List<ResolveJobReport> getAllResolveJobReportsById(Long id);
public List<ResolveJobReport> getAllResolveJobReportsById(Long id, RowBounds rowBounds);
public void saveResolveJobReport(ResolveJobReport resolveJobReport);
public void updateResolveJobReportById(ResolveJobReport resolveJobReport);
public void deleteResolveJobReporttById(Long id);
}
And the service class is as follows:
#Service("ResolveJobReportService")
public class ResolveJobReportService {
#Autowired
private ResolveJobReportMapper resolveJobReportMapper= null;
public List<ResolveJobReport> getAllResolveJobReports() {
return resolveJobReportMapper.getAllResolveJobReports();
}
public List<ResolveJobReport> getAllResolveJobReports(RowBounds rowBounds) {
return resolveJobReportMapper.getAllResolveJobReports();
}
public List<ResolveJobReport> getAllResolveJobReportsById(Long id) {
return resolveJobReportMapper.getAllResolveJobReportsById(id);
}
public List<ResolveJobReport> getAllResolveJobReportsById(Long id, RowBounds rowBounds) {
return resolveJobReportMapper.getAllResolveJobReportsById(id);
}
public void saveResolveJobReport(ResolveJobReport resolveJobReport) {
resolveJobReportMapper.saveResolveJobReport(resolveJobReport);
}
public void updateResolveJobReportById(ResolveJobReport resolveJobReport) {
resolveJobReportMapper.updateResolveJobReportById(resolveJobReport);
}
public void deleteResolveJobReporttById(Long id) {
resolveJobReportMapper.deleteResolveJobReporttById(id);
}
}
Can anyone see what is wrong.
The problem happens because the namespace in mapper xml is com.qlsdistribution.fps.resolverender.data.mybatis.ResolveJobReportMapper but the package the mapper interface is com.qlsdistribution.fps.resolverender.data.mybatis.mapper.ResolveJobReportMapper.
To fix it make sure they match.
Put it in application.properties mybatis.mapper-locations=classpath*:**/mappers/*Mapper.xml
For those people using MyBatis without xml in spring boot project:
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
Please check your spring boot application class, make sure your #MapperScan matches your dao package.
#MapperScan("com.jjs.videoservice.dao")
The path must be SAME as your dao package (contains your mapper interface), I ignored "dao" and caused the issue.
Hope it helps someone, thanks
I had the same error message when I changed my project from a JavaFX Project to a Maven Project.
I had to move all my xml mapper files to the resource folder. After that, worked just fine.
I hit this problem recenly, and checked everything that can be found in the internet. Cost me a whole day.
Finally I put the xml files in the same place with the interface java files, which solved the problem.
I think that is because for some reasons the xml files can not be found, and putting them there make them visiable.
I had the same issue
for me the fix was giving same filename for both the java (mapper interface class) and corresponding xml file
I had 2 mappers in the same package. It was the root cause of the problem. Once each mapper interface was moved to separate package, the problem was resolved.
in my case, I used the same name for mapper and java class but the mapping in mapper.xml was pointing to the wrong java class
I faced the same problem recently, I noticed, that I added the new method in the production xml mapper file by mistake and not in the actual xml mappers in resources folder. Once the actual xml mappers in resources folder was updated, it fixed the problem. So please make sure you update the right mapper files in your src folder that gets compiled.
Sometimes people do this mistake:
In resources folder the created folder like "org.my_app.mybatis", but the correct way is do separate folder for each part of package
-org
--my_app
---mybatis
It is hard to recognize when you do it in code editor.
Visually we have the same result
But actually a different structure
Green will work, red - won't.

Issue with creating Custom Tag Libraries in CQ5.5

I am creating a custom tag library and want to use it in one of my components. I have created a bundle which includes tag hello class which is extending TagSupport class and i created tags.tld file under my resource folder
In my pom.xml, I have used resource tag to include my .tld file in the generated jar file.
Here is my java class and tld file
TAG CLASS:-
package com.cb;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
/**
* Simple tag example to show how content is added to the
* output stream when a tag is encountered in a JSP page.
*/
public class Hello extends TagSupport {
private String name=null;
/**
* Getter/Setter for the attribute name
as defined in the tld file
* for this tag*/
public void setName(String value){
name = value;
}
public String getName(){
return(name);
}
/**
* doStartTag is called by the JSP container
when the tag is encountered */
public int doStartTag() {
try {
JspWriter out = pageContext.getOut();
out.println("<table border=\"1\">");
if (name != null)
out.println("<tr><td> Welcome <b>" + name +
"</b> </td></tr>");
else
out.println("<tr><td> Hello World </td></tr></table>");
} catch (Exception ex) {
throw new Error("All is not well in the world.");
}
// Must return SKIP_BODY because we are not
//supporting a body for this
// tag.
return SKIP_BODY;
}
/**
* doEndTag is called by the
JSP container when the tag is closed */
public int doEndTag(){
return EVAL_PAGE;
}
}
I also successfully installed the bundle in my felix console without having any error. Then i written custom tag in my jsp as below
JSP:-
<%#include file="/libs/foundation/global.jsp"%>
<%# page import="com.testcb.TestCustomTag"%>
<%# taglib prefix="mytest" uri="http://cs.test.com/bundles/cq/1.8"%>
<mytest:hello name="sachin"></mytest:hello>
I am getting the like "org.apache.sling.api.scripting.ScriptEvaluationException: org.apache.sling.scripting.jsp.jasper.JasperException: /apps/test/components/content/test/test.jsp(4,0) Unable to load tag handler class "com.cb.Hello" for tag "mytest:hello".
The same code is working fine in my apache tomcat server without having any issue. I am getting the error when i incorporate it in CQ.
What am i doing here? Is there any config i need to do in OSGI console to make it available?
UPDATE:
There was some problem with package name. Now Sling can read my tag handler class after i renamed the package name.
The error "Unable to load tag handler class" also has gone.
Now i am getting error as "org.apache.sling.api.scripting.ScriptEvaluationException: javax.servlet.ServletException: javax.servlet.jsp.JspException: com.testcb.TestCustomTag cannot be cast to javax.servlet.jsp.tagext.Tag"
I have the following dependency in pom.xml
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
</dependency>
And Here is my tld
<?xml version="1.0" encoding="ISO-8859-1" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0">
<description>My tag library123</description>
<tlib-version>1.0</tlib-version>
<short-name>TagLib-Test</short-name>
<uri>http://cs.test.com/bundles/cq/1.0</uri>
<jspversion>2.1</jspversion>
<tag>
<name>testcustomtag</name>
<tagclass>com.testcb.TestCustomTag</tagclass>
<bodycontent>empty</bodycontent>
<info>This is a simple hello tag</info>
<attribute>
<name>name</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
Is there any problem with jsp version?
Please guide me to resolve.
Thanks
The tags.tld file needs to be under the META-INF folder. If you don't have it already you can create one under your resources source folder.
Yes, It is working as expected after i removed tag in pom.xml. This was the cause issues. :)
Thanks !

Spring Configuration of Custom Apache Camel Data Format

I am using Apache Camel 2.9.2 and Spring 3.0.6.RELEASE. I am trying to use a custom DataFormat to marshal and unmarshal Camel messages. I want to configure my custom DataFormat into one of my routes using Spring.
Apache Camel's documentation states that in order to hook up my custom Data Format to a route in Spring I simply need to declare my custom DataFormat as a bean and reference it inside of my Spring route like so:
<marshal>
<custom ref="myCustomDataFormat"/>
</marshal>
http://camel.apache.org/custom-dataformat.html
So I have the following setup:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
">
<bean id="myCustomDataFormat" class="com.test.CustomDataFormat"/>
<!-- Camel Context -->
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="file:C:/test?initialDelay=4000&delay=1000"/>
<marshal>
<custom ref="myCustomDataFormat"/>
</marshal>
<to uri="file:C:/test2"/>
</route>
</camelContext>
</beans>
But when I try to start Camel, I get the following nasty error:
org.springframework.beans.ConversionNotSupportedException: Failed to convert value of type 'com.test.CustomDataFormat' to required type 'org.apache.camel.model.DataFormatDefinition'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [com.test.CustomDataFormat] to required type [org.apache.camel.model.DataFormatDefinition]: no matching editors or conversion strategy found
My Data Format is defined as follows:
package com.test;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.camel.Exchange;
import org.apache.camel.spi.DataFormat;
public class CustomDataFormat implements DataFormat {
/* (non-Javadoc)
* #see org.apache.camel.spi.DataFormat#marshal(org.apache.camel.Exchange, java.lang.Object, java.io.OutputStream)
*/
#Override
public void marshal(Exchange exchange, Object graph, OutputStream stream)
throws Exception {
System.out.println("Marshal");
byte[] bytes = exchange.getContext().getTypeConverter().mandatoryConvertTo(byte[].class, graph);
stream.write(bytes);
}
/* (non-Javadoc)
* #see org.apache.camel.spi.DataFormat#unmarshal(org.apache.camel.Exchange, java.io.InputStream)
*/
#Override
public Object unmarshal(Exchange exchange, InputStream stream)
throws Exception {
System.out.println("Unmarshal");
byte[] bytes = exchange.getContext().getTypeConverter().mandatoryConvertTo(byte[].class, stream);
return bytes;
}
}
I know that my CustomDataFormat implementation is correct because I created the following test route in Java and it worked flawlessly
package com.test;
import org.apache.camel.spring.SpringRouteBuilder;
public class TestFormatRoute extends SpringRouteBuilder {
/* (non-Javadoc)
* #see org.apache.camel.builder.RouteBuilder#configure()
*/
#Override
public void configure() throws Exception {
from("file:C:/test?initialDelay=4000&delay=1000").unmarshal(new CustomDataFormat()).to("file:C:/test2");
}
}
What am I missing?
Thanks
Update
After letting Camel completely start up after receiving this error I found to my disbelief that my custom data format actually does work in the route that I created. I'm not sure what process is attempting to parse my custom data format and failing but it is apparently not the same process parsing the data format to put into my route.
This solves the functional requirement of the data format, but it does not explain why I am receiving this error.
I have also confirmed that it was not the name of my data format (CustomDataFormat) that was causing the issue. Renaming my DataFormat to a unique name (MerlinDataFormat) did not fix the error.
I still would like to know why I am receiving this error since large blocks of ugly red errors in my console and log files aren't exactly appealing.
Thanks again.
It turned out to be a pretty simple solution (and one that I admit should have been easy to see). There are actually two ways to go about solving this issue, one of them using only spring and one of them requiring an additional java class.
Solution 1
Create a new class extending DataFormatDefinition which has the same properties as your custom DataFormat. Override the configureDataFormat() method to set all of the properties of the underlying DataFormat. Add constructor(s) to set the underlying DataFormat as an instance of your CustomDataFormat. Now you should be able to create an instance of your DataFormatDefinition in spring and reference it when marshaling or unmarshaling.
Solution 2 (Quick & Dirty)
In spring, create a new DataFormatDefinition bean and set it's dataFormat property as a reference to your DataFormat spring bean. Now you should be able to reference your DataFormatDefinition bean when marshaling or unmarshaling.
Not really sure what's wrong with your example, it seems just fine. Can you post your code for the data format? Are you implementing org.apache.camel.spi.DataFormat correctly?
I just set up this example with Camel 2.9.2 and it works like a charm. The Custom data format is the one from Camel documentation/source code.
<bean id="mySweetDf" class="com.example.MySweetDf"/>
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="file:C:/temp/test?initialDelay=4000&delay=1000"/>
<marshal>
<custom ref="mySweetDf"/>
</marshal>
<convertBodyTo type="java.lang.String"/>
<to uri="file:C:/temp/test2"/>
</route>
</camelContext>
data format java file:
package com.example;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.camel.Exchange;
import org.apache.camel.spi.DataFormat;
public class MySweetDf implements DataFormat {
public void marshal(Exchange exchange, Object graph, OutputStream stream) throws Exception {
byte[] bytes = exchange.getContext().getTypeConverter().mandatoryConvertTo(byte[].class, graph);
String body = reverseBytes(bytes);
stream.write(body.getBytes());
}
public Object unmarshal(Exchange exchange, InputStream stream) throws Exception {
byte[] bytes = exchange.getContext().getTypeConverter().mandatoryConvertTo(byte[].class, stream);
String body = reverseBytes(bytes);
return body;
}
private String reverseBytes(byte[] data) {
StringBuilder sb = new StringBuilder(data.length);
for (int i = data.length - 1; i >= 0; i--) {
char ch = (char) data[i];
sb.append(ch);
}
return sb.toString();
}
}
UPDATE
Just tried you code. Seems to work as well. Created a fresh camel 2.9.2 project via mvn archetype 168: remote -> org.apache.camel.archetypes:camel-archetype-spring (Creates a new Camel project with added Spring DSL support.). This does only include camel-core and camel-spring dependencies, nothing else.
Then replaced camel-context.xml with your xml and added your data format code in the java directory. A run with "mvn camel:run" copied the file and printed "marshal" in the log.
[pache.camel.spring.Main.main()] SpringCamelContext INFO Route: route1 started and consuming from: Endpoint[file://C:/test?delay=1000&initialDelay=4000]
[pache.camel.spring.Main.main()] SpringCamelContext INFO Total 1 routes, of which 1 is started.
[pache.camel.spring.Main.main()] SpringCamelContext INFO Apache Camel 2.9.2 (CamelContext: camel-1) started in 0.808 seconds
Marshal
Are you sure you have all dependencies setup correctly and not some .jar file that messes things up with Data formats?
UPDATE2
Okay, I think I have an idea what it is:
http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/model/dataformat/CustomDataFormat.html
Camel already have a class named as your data format. You should try rename it to something else. CustomDataFormat extends org.apache.camel.model.DataFormatDefinition which is referred to in your error. Java should handle this, since it's two different namespaces, but there might be some issue in your project setup that causes this conflict. Try to rename the data format and see if that solves the problem.
I too was facing the same issue with camel 2.10.0. If you provide the ref with an instance of type org.apache.camel.model.DataFormatDefinition everything works fine!! I can see two classes for xmljson conversion --> XmlJsonDataFormat implementing both DataFormat and DataFormatDefinition.
I solved the same issue that I too was facing.
Implemented a class extending DataFormatDefintion - which in it's configureDataFormat method sets injectable properties for the class that extends DataFormat (in your case this is CustomDataFormat).
I used XmlJson conversion as a template to solve.

Resources