Freemarker encoding wrong - java

I have project it's jetty server which use freemarker. I use russian letters in my templates and receive ?. All subjects i have read before didn't help me.
I use in my code
.setContentType("text/html;charset=utf-8");
.setCharacterEncoding("UTF-8");
all my files is utf-8.
My Freemarker page genertor servlet
public class PageGenerator {
private static PageGenerator pageGenerator;
private Configuration cfg;
public static PageGenerator instance() {
if (pageGenerator == null)
pageGenerator = new PageGenerator();
return pageGenerator;
}
public String getPage(String filename, Map<String, Object> data) {
Writer stream = new StringWriter();
try {
Template template = cfg.getTemplate(filename);
template.process(data, stream);
} catch (IOException | TemplateException e) {
e.printStackTrace();
}
return stream.toString();
}
private PageGenerator() {
cfg = setCfg();
}
private Configuration setCfg(){
cfg = new Configuration(Configuration.VERSION_2_3_20);
try {
cfg.setDirectoryForTemplateLoading(new File("templates/"));
cfg.setDefaultEncoding("UTF-8");
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
} catch (IOException e) {
e.printStackTrace();
}
return cfg;
}
}
But in brouser my page in windows-1252 encoding.

Thanks for idea ddekany I used debag mode and find out that Class Response that extends HttpServletResponse has "magic" method .setCharacterEncoding() which set Character Encoding in response stream

Related

Convert html to Pdf with with very big data

I have implemented html to pdf conversion using openhtmltopdf and I use it in Struts 2 action and it works very well. However, in the case of very large data, e.g. the html data is > 3Mb (pdf file ~1.6Mb) when I test it with JMeter for 50 hits the application crashes with message java.lang.OutOfMemoryError: Java heap space.
If I increase the java limit with the -Xmx option I just get some extra hits
The code i use is like this:
First clean html
public class HtmlToXhtmlConverterHTMLCleaner2 extends AbstractHtmlToXhtmlConverter
implements IHtmlToXhtmlConverter {
public HtmlToXhtmlConverterHTMLCleaner2(String htmlData) {
super(htmlData);
}
#Override
public void convert() {
final HtmlCleaner cleaner = new HtmlCleaner();
CleanerProperties cleanerProperties = cleaner.getProperties();
cleanerProperties.setAdvancedXmlEscape(true);
cleanerProperties.setOmitXmlDeclaration(true);
cleanerProperties.setOmitDoctypeDeclaration(false);
cleanerProperties.setTranslateSpecialEntities(true);
cleanerProperties.setTransResCharsToNCR(true);
cleanerProperties.setRecognizeUnicodeChars(true);
cleanerProperties.setIgnoreQuestAndExclam(true);
cleanerProperties.setUseEmptyElementTags(false);
cleanerProperties.setPruneTags("script");
final XmlSerializer xmlSerializer = new PrettyXmlSerializer(cleanerProperties);
try {
final TagNode rootTagNode = cleaner.clean(htmlData);
this.xhtmlData = xmlSerializer.getAsString(rootTagNode);
} catch (Exception ex) {
ex.printStackTrace();
}
}
then convert cleaned html to pdf
public class PDFConverterHtmlToPdf extends AbstractPDFConverter implements IPDFConverter {
ByteArrayOutputStream psfData;
public PDFConverterHtmlToPdf(String xhtmlData, String cssFile) {
super();
this.xhtmlData = xhtmlData;
this.cssFile = cssFile;
}
#Override
public void convert() {
pdfData = new ByteArrayOutputStream();
try {
// There are more options on the builder than shown below.
PdfRendererBuilder builder = new PdfRendererBuilder();
if(cssFile != null && cssFile.length() > 0){
builder.withHtmlContent(xhtmlData, cssFile);
} else {
builder.withHtmlContent(xhtmlData, "");
}
builder.toStream(pdfData);
builder.run();
} catch (Exception e) {
e.printStackTrace();
}
}
}
then send data from strus2 action to request
private void buildPdfContent(String htmlContent) {
String pdfConverterCssFile = "http://localhost:8080/DocumentConverterApi/css/htmlToPdf.css";
PDFConverterHelp pdfConverterHelp = new PDFConverterHelp("demo.pdf",
htmlContent, pdfConverterCssFile);
pdfConverterHelp.build();
inputStream = new ByteArrayInputStream(pdfConverterHelp.getPDFFile().toByteArray());
pdfConverterHelp.closePdfData();
contentDisposition = "inline;filename=\"" + "demo.pdf\"";
}
I'm doing something wron?
Is there any other way to implement it without the risk of crashing the application?

How to convert this method from using java.io.File to java.nio.file?

Basically I have this method that I got off a tutorial (My main goal is to simply return the images from the spring boot server so that I could dynamically view them in Angular)
#RestController
public class FileController {
#Autowired
ServletContext context;
#GetMapping(path = "/allImages")
public ResponseEntity<List<String>> getImages(){
List<String> images = new ArrayList<String>();
String filesPath = context.getRealPath("/images");
File fileFolder = new File(filesPath);
if(fileFolder!=null) {
for(final File file : fileFolder.listFiles()) {
if(!file.isDirectory()) {
String encodeBase64 = null;
try {
String extention = FilenameUtils.getExtension(file.getName());
FileInputStream fileInputStream = new FileInputStream(file);
byte[] bytes = new byte[(int)file.length()];
encodeBase64 = Base64.getEncoder().encodeToString(bytes);
images.add("data:image/"+extention+";base64,"+encodeBase64);
fileInputStream.close();
} catch (Exception e) {
// TODO: handle exception
}
}
}
}
return new ResponseEntity<List<String>>(HttpStatus.OK);
}
With the current code, when I try to return the files, I get:
java.lang.NullPointerException: Cannot read the array length because the return value of "java.io.File.listFiles()" is null
I've been searching around and noticed that people recommend using java.nio.file instead but I'm a little lost on how would I implement this here. Any help is appreciated.
Example with nio:
public List<String> readImages() throws IOException {
return Files.list(Path.of("/images"))
.filter(Files::isRegularFile)
.map(this::encode)
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
private String encode(Path file) {
try {
String extension = FilenameUtils.getExtension(file.getFileName().toString());
String encodeBase64 = Base64.getEncoder().encodeToString(Files.readAllBytes(file));
return "data:image/"+extension+";base64,"+encodeBase64;
} catch (Exception e) {
return null;
}
}
First get a Path to your folder:
Path folderPath = Paths.get(filesPath);
If your Path points to a directory, you can get a Stream<Path> of its contents using Files.list:
if (Files.isDirectory(folderPath)) {
List<Path> files = Files.list(folderPath)
.filter(path -> !Files.isDirectory(path))
.collect(Collectors.toList());
// Do something with the files.
}
It doesn't look like you are using the FileInputStream for anything, so you shouldn't need to translate that part. To get the file extension of your path, you probably need to convert the Path to a string, and extract the extension yourself.
I solved this issue with this code:
#Autowired
ServletContext context;
#GetMapping(path = "/allImages")
public List<String> readImages() throws IOException {
return Files.list(Paths.get(context.getRealPath("/images")))
.filter(Files::isRegularFile)
.map(this::encode)
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
private String encode(Path file) {
try {
String extension = FilenameUtils.getExtension(file.getFileName().toString());
String encodeBase64 = Base64.getEncoder().encodeToString(Files.readAllBytes(file));
return "data:image/"+extension+";base64,"+encodeBase64;
} catch (Exception e) {
return null;
}
}
Thank you to everyone who helped.

CXF message's context outside of interceptors

I'm sending a SOAP message using apache cxf and what I want is to get both request and response payloads after the call is finished. Currently I'm using two interceptors and put payloads into messages' context like that message.getExchange().put(ExchangeContextEnum.RESPONSE_PAYLOAD.toString(), new String(payload, Charset.forName(StandardCharsets.UTF_8.name())));.
I don't want to process them right away in the interceptor itself because I need requests and responses for the series of calls. Also, I'd like to avoid making any kind of storage for the sake of simplicity and not having to deal with possible concurrency issues.
Can I get those values after the call is finished or the context is completely lost at this point?
Some code:
webService.call(object)
//here i'd like to get payloads
Interceptor for response:
public class LogInInterceptor extends AbstractPhaseInterceptor<Message> {
public LogInInterceptor() {
super(Phase.RECEIVE);
}
#Override
public void handleMessage(Message message) throws Fault {
InputStream in = message.getContent(InputStream.class);
byte payload[] = new byte[0];
try {
payload = IOUtils.readBytesFromStream(in);
} catch (IOException e) {
e.printStackTrace();
}
ByteArrayInputStream bin = new ByteArrayInputStream(payload);
message.setContent(InputStream.class, bin);
message.getExchange().put(ExchangeContextEnum.RESPONSE_PAYLOAD.toString(), new String(payload, Charset.forName(StandardCharsets.UTF_8.name())));
}
}
Interceptor for request:
public class WSSLogOutInterceptor extends AbstractSoapInterceptor {
public WSSLogOutInterceptor() {
super(Phase.USER_PROTOCOL);
}
#Override
public void handleMessage(SoapMessage message) throws Fault {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
SOAPMessage messageContent = message.getContent(SOAPMessage.class);
messageContent.writeTo(baos);
message.getExchange().put(ExchangeContextEnum.REQUEST_PAYLOAD.toString(), baos.toString());
} catch (SOAPException | IOException e) {
throw new Fault(e);
}
}
}
I ended up with the following solution:
Instead of putting values in message's exchange i simply do message.put(key, value) in the interceptor. To get those values after the call you
need to get response context like that (String) ((BindingProvider) webService).getResponseContext().get(key) where key is the same value you used before to put payload in the message. Now here's the problem - you won't find values that you put in the outgoing chain in response context. You can use simple workaround and put value in the exchange of the message and then, in the ingoing chain get it and put it into message. Pay attention to the phase I used (POST_PROTOCOL), it'd helpful if you use WSS.
Here's the code:
public class LoggingOutPayloadInterceptor extends AbstractSoapInterceptor {
public static final String OUT_PAYLOAD_KEY = "use.your.package.name.OUT_PAYLOAD_KEY";
public LoggingOutPayloadInterceptor() {
super(Phase.POST_PROTOCOL);
}
#Override
public void handleMessage(SoapMessage soapMessage) throws Fault {
Document document = soapMessage.getContent(SOAPMessage.class).getSOAPPart();
StringWriter stringWriter = new StringWriter();
try {
TransformerFactory.newInstance().newTransformer().transform(new DOMSource(document), new StreamResult(stringWriter));
} catch (TransformerException e) {
e.printStackTrace();
}
soapMessage.getExchange().put(OUT_PAYLOAD_KEY, stringWriter.toString());
}
}
public class LoggingInPayloadInterceptor extends AbstractSoapInterceptor {
public static final String IN_PAYLOAD_KEY = "use.your.package.name.IN_PAYLOAD";
public LoggingInPayloadInterceptor() {
super(Phase.POST_PROTOCOL);
addAfter(SAAJInInterceptor.class.getName());
}
#Override
public void handleMessage(SoapMessage message) throws Fault {
Document document = message.getContent(SOAPMessage.class).getSOAPPart();
StringWriter stringWriter = new StringWriter();
try {
TransformerFactory.newInstance().newTransformer().transform(new DOMSource(document), new StreamResult(stringWriter));
} catch (TransformerException e) {
e.printStackTrace();
}
message.put(IN_PAYLOAD_KEY, stringWriter.toString());
message.put(LoggingOutPayloadInterceptor.OUT_PAYLOAD_KEY, message.getExchange().get(LoggingOutPayloadInterceptor.OUT_PAYLOAD_KEY));
}
}
webService.call(...);
String inPayload = (String)((BindingProvider)webService).getResponseContext().get(LoggingInPayloadInterceptor.IN_PAYLOAD_KEY);
String outPayload = (String) ((BindingProvider) webService).getResponseContext().get(LoggingOutPayloadInterceptor.OUT_PAYLOAD_KEY);

jsonschema2pojo not generating pojo classes from json string

I was following the link Generate Java class from JSON? to create the POJO classes from json string (and not from schema). I am using jsonschema2pojo jar of version 0.4.10 but could not able to generate the POJO class.
My code is as below,
public class App
{
public static void main( String[] args )
{
JCodeModel codeModel = new JCodeModel();
try {
URL source = new URL("file:///C://Users//...//accession.json");
new SchemaMapper().generate(codeModel, "Accession", "com.test", source);
File dir = new File("D://test");
if(dir.exists()){
System.out.println("dir available");
codeModel.build(dir);
}else{
System.out.println("dir not available");
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
So accession.json has json string which need to be converted into POJO. Can anybody please help me here.
I had a similar experience using the command-line tool. In my case, it was the result of not correctly specifying the source type (JSONSCHEMA or JSON; default: JSONSCHEMA).
I think your problem is similar: You're using the default (no-args) constructor for SchemaMapper. The following steps should solve the problem:
Subclass org.jsonschema2pojo.DefaultGenerationConfig, overriding getSourceType() to return SourceType.JSON
Use an instance of that subclass for the SchemaMapper(RuleFactory ruleFactory, SchemaGenerator schemaGenerator) constructor (instead of the no-args constructor).
Once I faced the same problem and then I resolved this.
In your code you are using Default Configuration which takes Source Type Jason Schema.
But when You are giving input Jason you have to set this return type in this way :
SourceType.JSON in your Configuration.
class App
{
public static void main( String[] args )
{
JCodeModel codeModel = new JCodeModel();
try {
URL source= new URL("file:///D:/temp.json");
GenerationConfig config = new DefaultGenerationConfig() {
#Override
public boolean isGenerateBuilders() {
return true;
}
public SourceType getSourceType(){
return SourceType.JSON;
}
};
SchemaMapper mapper =new SchemaMapper(new RuleFactory(config, new GsonAnnotator(), new SchemaStore()), new SchemaGenerator());
mapper.generate(codeModel, "Accession", "com.test", source);
File dir = new File("D://");
if(dir.exists()){
System.out.println("dir available");
codeModel.build(dir);
}else{
System.out.println("dir not available");
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I hope It will help you..
Good Luck !!
I also struggled a bit with this. I did the following in the end:
Created my own GenerationConfig, overriding getSourceType:
static class MyConfig extends DefaultGenerationConfig {
#Override
public SourceType getSourceType() {
return SourceType.JSON;
}
}
I then initialised the build process as follows:
private void parseFileExample() {
URL source = new URL("file:/tmp/input/blah.json");
JCodeModel codeModel = new JCodeModel();
MyConfig generationConfig = new MyConfig();
RuleFactory ruleFactory = new RuleFactory(generationConfig, new GsonAnnotator(), new SchemaStore());
SchemaGenerator generator = new SchemaGenerator();
SchemaMapper mapper = new SchemaMapper(ruleFactory, generator);
mapper.generate(codeModel, "MyClass", "com.drakedroid", source);
codeModel.build(new File("/tmp/output/"));
}
The trick here was, to use an URL. The mapper.generate didn't work when I passed in just a string.
Thanks #Kapil, your answer helped me.
This program allows us to generate POJO classes according to predefined JSON.
We can also use it at runtime, where JSON response is not known, write the JSON response to the file and read it accordingly using the following code.
public class JSONExample {
public static void main(String... args) {
JCodeModel codeModel = new JCodeModel();
try
{
// In sample.json I have already pasted a JSON
File file=new File("//root//AndroidStudioProjects//MyApplication//sample.json");
URL source = file.toURI().toURL();
GenerationConfig config = new DefaultGenerationConfig() {
#Override
public boolean isGenerateBuilders()
{
return true;
}
public SourceType getSourceType()
{
return SourceType.JSON;
}
};
SchemaMapper mapper = new SchemaMapper(new RuleFactory(config, new Jackson2Annotator(), new SchemaStore()), new SchemaGenerator());
try {
// The ClassName is the main class that will contain references to other generated class files
// com.example is the package name
mapper.generate(codeModel, "ClassName", "com.example", source);
} catch (IOException e) {
e.printStackTrace();
}
try {
// Directory where classes will be genetrated
File file1=new File("//root//AndroidStudioProjects//MyApplication//");
if (file1.exists())
{
System.out.println("dir available");
codeModel.build(file1);
}
else
{
System.out.println("dir not available");
}
System.out.println(""+file1+" Exists "+file1.exists());
} catch (IOException e) {
e.printStackTrace();
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}

Load java properties inside static initializer block

I have a static util class that does some string manipulation on a bit sensitive data.
Prior to use of this class I need to initialize certain static variables with values, such as usernames/password, that I prefer to store in a .properties file.
I am not very familiar with how loading of .properties file work in Java, especially outside of *Spring DI *container.
Anyone can give me a hand/insight on how this can be done?
Thank you!
Addition: .properties file precise location is unknown, but it will be on the classpath. Sorta like classpath:/my/folder/name/myproperties.propeties
First, obtain an InputStream from which the properties are to be loaded. This can come from a number of locations, including some of the most likely:
A FileInputStream, created with a file name that is hard-coded or specified via a system property. The name could be relative (to the current working directory of the Java process) or absolute.
A resource file (a file on the classpath), obtained through a call to getResourceAsStream on the Class (relative to the class file) or ClassLoader (relative to the root of the class path). Note that these methods return null if the resource is missing, instead of raising an exception.
A URL, which, like a file name, could be hard-coded or specified via a system property.
Then create a new Properties object, and pass the InputStream to its load() method. Be sure to close the stream, regardless of any exceptions.
In a class initializer, checked exceptions like IOException must be handled. An unchecked exception can be thrown, which will prevent the class from being initialized. That, in turn, will usually prevent your application from running at all. In many applications, it might be desirable to use default properties instead, or fallback to another source of configuration, such as prompting a use in an interactive context.
Altogether, it might look something like this:
private static final String NAME = "my.properties";
private static final Properties config;
static {
Properties fallback = new Properties();
fallback.put("key", "default");
config = new Properties(fallback);
URL res = MyClass.getResource(NAME);
if (res == null) throw new UncheckedIOException(new FileNotFoundException(NAME));
URI uri;
try { uri = res.toURI(); }
catch (URISyntaxException ex) { throw new IllegalArgumentException(ex); }
try (InputStream is = Files.newInputStream(Paths.get(uri))) { config.load(is); }
catch (IOException ex) { throw new UncheckedIOException("Failed to load resource", ex); }
}
Check out java.util.Properties.
You can use a static initializer. So on the top of the class you can do:
static {
Properties props = new Properties();
InputStream steam = ...; // open the file
props.load(stream);
// process properties content
String username = props.getProperty("username");
}
Use either:
CurrentClassName.class.getResourceAsStream
new FileInputStream(File)
to get the input stream depending on if the class is in or out of the classpath. Then use
Properties.load
to load the properties.
It's been a while, but if I remember correctly you just do something like this:
Properties prop = new Properties();
prop.load(new FileInputStream(filename));
//For each property you need.
blah = prop.getProperty(propertyname);
Well with static Properties it would make sense to initialize them as a Singleton which will be loaded once in a class. Here's an example:
class Example
{
public final static String PROPSFILE = "test.properties";
private static Properties props;
protected static Properties getProperties()
{
if(props == null)
{
props = new Properties();
props.load(new FileInputStream(new File(PROPSFILE));
}
return props;
}
public static User getUser()
{
String username = getProperties().getProperty("username");
return new User(username);
}
}
If you use relative Pathnames you should make sure, that your classpath is setup righ.
for me MyClass.class.getClassLoader().getResourceAsStream(..) did the trick:
private static final Properties properties;
static {
Properties fallback = new Properties();
fallback.put(PROP_KEY, FALLBACK_VALUE);
properties = new Properties(fallback);
try {
try (InputStream stream = MyClass.class.getClassLoader().getResourceAsStream("myProperties.properties")) {
properties.load(stream);
}
} catch (IOException ex) {
// handle error
}
}
I agree with #Daff, maybe better to use singleton class...this what i have on my project for similar requirement, maybe it may help:
clients of the class can use it like this:
ConfigsLoader configsLoader = ConfigsLoader.getInstance("etc/configs.xml");
System.out.format("source dir %s %n", configsLoader.getSourceDir());
and then the class:
public class ConfigsLoader {
private String sourceDir;
private String destination;
private String activeMqUrl;
private static Logger log = Logger.getLogger(ConfigsLoader.class.getName());
private static ConfigsLoader instance = null;
private ConfigsLoader(String configFileName) {
log.info("loading configs");
Properties configs = new Properties();
try {
configs.loadFromXML(new FileInputStream(configFileName));
sourceDir = configs.getProperty("source.dir");
destination = configs.getProperty("destination");
activeMqUrl = configs.getProperty("activemqconnectionurl");
configs.setProperty("lastLoaded", new SimpleDateFormat("yyyy-M-d HH:mm").format(new Date()));
configs.storeToXML(new FileOutputStream(configFileName), "saving last modified dates");
} catch (InvalidPropertiesFormatException e) {
log.log(Level.SEVERE,"Error occured loading the properties file" ,e);
} catch (FileNotFoundException e) {
log.log(Level.SEVERE,"Error occured loading the properties file" ,e);
} catch (IOException e) {
log.log(Level.SEVERE,"Error occured loading the properties file" ,e);
}
}
public static ConfigsLoader getInstance(String configFileName) {
if(instance ==null) {
instance = new ConfigsLoader(configFileName);
}
return instance;
}
public String getSourceDir() {
return sourceDir;
}
public void setSourceDir(String sourceDir) {
this.sourceDir = sourceDir;
}
public String getDestination() {
return destination;
}
public void setDestination(String destination) {
this.destination = destination;
}
public String getActiveMqUrl() {
return activeMqUrl;
}
public void setActiveMqUrl(String activeMqUrl) {
this.activeMqUrl = activeMqUrl;
}
}
I did this finally using getResourceAsStream() fuction associated with the class in which the static code block is being written.
//associate Property and ImputStream imports
public class A {
static Properties p;
static {
p = new Properties();
try {
InputStream in = A.class.getResourceAsStream("filename.properties");
p.load(in);
} catch (FileNotFoundException e) {
System.out.println("FileNotFoundException");
e.printStackTrace();
} catch (IOException e) {
System.out.println("IOException");
e.printStackTrace();
}
}
.
.
.
}

Categories

Resources