Hi!
Ever wondered how many abstractions you have to learn in order to use the API?
I just started to read about websocket api in java and it seems you need a lot to understand in order be on the same wave.
Lets start with RFC 6455, then you need to read JSR-356.
You think this is enough? :-)
If you use Spring then it provides you with WebSocketConfigurer which mimicries the low level web socket api.
If you do not like to play with low level api, then you can use AbstractWebSocketMessageBrokerConfigurer which adds messaging model with queues and topics using STOMP over websocket api and fallback for the clients who do not have websocket at hand.
You can also add external message broker which will serve your messages.
But what about security?
You have to use AbstractSecurityWebSocketMessageBrokerConfigurer in order to configure security.
So, together with security this will be 5 apis\concepts you need to know just in order to play with web sockets.
Is not that much?
This blog is a collection of minds around linux, java, javascript, etc. Looking for great opportunities.
Показаны сообщения с ярлыком java. Показать все сообщения
Показаны сообщения с ярлыком java. Показать все сообщения
пятница, 17 июля 2020 г.
суббота, 7 апреля 2018 г.
Kotlin. Good point.
Hi!
Long time no see.
What I'm currently observing is the rise of Kotlin language. Kotlin is the child of JetBrains company which brought to us IntelliJ.
Why Kotlin could in the future replace Java? What are the selling points of Kotlin?
Let's try to figure this out:
Long time no see.
What I'm currently observing is the rise of Kotlin language. Kotlin is the child of JetBrains company which brought to us IntelliJ.
Why Kotlin could in the future replace Java? What are the selling points of Kotlin?
Let's try to figure this out:
- Kotlin works on JVM.
- Kotlin can use all the java libraries.
- Java can call code written in Kotlin.
- Kotlin is open source.
- Kotlin is developed and supported by JetBrains.
- Google officially supports Kotlin as a second development language on Android platform.
- IntelliJ has very good support tooling for Kotlin.
- Spring Boot supports Kotlin.
- Spring Framework 5 supports Kotlin.
- Kotlin can be translated to java script.
With Kotlin you can migrate the project in Java in small steps.
Is not it enough to sell Kotlin to management and start using it in production?
четверг, 22 декабря 2016 г.
Java Jackson 2. Custom Date deserialization in JSON.
Hi. I want to share receipt with you how to write custom date deserializator for Jackson 2. This could be helpful when you deserialize value into generic Map and want that dates actually were stored like java.util.Date not String.
Deserialization usually done like so:
Map<String,Object> data = null;
data = mapper.readValue(someInputStream,Map.class);
In order to create custom serializator one needs to extend the class com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer. Here is the example of custom date deserializator:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonTokenId;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class DDeserializer extends UntypedObjectDeserializer
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
@Override
public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
if (jp.getCurrentTokenId() == JsonTokenId.ID_STRING) {
try {
LocalDate localDate = LocalDate.parse(jp.getText(),formatter);
java.util.Date date = java.sql.Date.valueOf(localDate);
return date;
} catch (Exception e) {
return super.deserialize(jp, ctxt);
}
} else {
return super.deserialize(jp, ctxt);
}
}
public static ObjectMapper regObjectMapper(ObjectMapper mapper){
SimpleModule simpleModule = new SimpleModule();
simpleModule.addDeserializer(Object.class, new DDeserializer());
mapper.registerModule(simpleModule);
return mapper;
}
}
Please note, that here is java 8 Date & Time API is mixed with plain old Date API. But the approach here is important.
Take a note in regObjectMapper method. In order to use custom deserializator it needs to be registered in ObjectMapper. After this you could use it to deserealize strings in to Date.
Deserialization usually done like so:
Map<String,Object> data = null;
data = mapper.readValue(someInputStream,Map.class);
In order to create custom serializator one needs to extend the class com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer. Here is the example of custom date deserializator:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonTokenId;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class DDeserializer extends UntypedObjectDeserializer
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
@Override
public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
if (jp.getCurrentTokenId() == JsonTokenId.ID_STRING) {
try {
LocalDate localDate = LocalDate.parse(jp.getText(),formatter);
java.util.Date date = java.sql.Date.valueOf(localDate);
return date;
} catch (Exception e) {
return super.deserialize(jp, ctxt);
}
} else {
return super.deserialize(jp, ctxt);
}
}
public static ObjectMapper regObjectMapper(ObjectMapper mapper){
SimpleModule simpleModule = new SimpleModule();
simpleModule.addDeserializer(Object.class, new DDeserializer());
mapper.registerModule(simpleModule);
return mapper;
}
}
Please note, that here is java 8 Date & Time API is mixed with plain old Date API. But the approach here is important.
Take a note in regObjectMapper method. In order to use custom deserializator it needs to be registered in ObjectMapper. After this you could use it to deserealize strings in to Date.
четверг, 23 июля 2015 г.
Singleton pattern in java
Currently I'm interested in software patterns. I'm reading the classic book: "Design patterns. Elements of reusable object-oriented software".
One of the patterns described is singleton. This is a popular pattern in java. So, how could you develop it java?
class Singleton{
private static Singleton singleton;
private Singleton{}
public static synchronized Singleton getInstance() {
if (instance == null) instance = new Singleton();
return instance;
}
}
But, how about this?
public enum Singleton{
INSTANCE;
public void yourBusinessMethod(){}
}
A single-element enum type is the best way to implement a singleton. This is stated in "Effective Java".
What are the pros of this solution?
One of the patterns described is singleton. This is a popular pattern in java. So, how could you develop it java?
class Singleton{
private static Singleton singleton;
private Singleton{}
public static synchronized Singleton getInstance() {
if (instance == null) instance = new Singleton();
return instance;
}
}
But, how about this?
public enum Singleton{
INSTANCE;
public void yourBusinessMethod(){}
}
A single-element enum type is the best way to implement a singleton. This is stated in "Effective Java".
What are the pros of this solution?
- no serialization problems
- guarantee against multiple instantiation
- easy to read (less) code
среда, 22 октября 2014 г.
Java Jackson 1. Serialize\Deserialize java.util.Date <-> JSON
In WebSphere Application Server 8.5.5 there is built in support for developing REST services with Jackson 1 and Apache wink projects.
How can you work with dates in jackson 1?
How can you work with dates in jackson 1?
вторник, 30 сентября 2014 г.
Bouncy Castle and Crypto Pro. Detach signature from signed data.
In this post I will write how to:
1) detach signature that is attached to the data
2) view the content of signature.
Bouncy Castle is a good library but it is hard to find something in its documentation.
Here is the class that detaches the signature and writes the content of data to the File:
1) detach signature that is attached to the data
2) view the content of signature.
Bouncy Castle is a good library but it is hard to find something in its documentation.
Here is the class that detaches the signature and writes the content of data to the File:
среда, 3 июля 2013 г.
Book review. Java EE 6 Cookbook for Securing, Tuning, and Extending Enterprise Applications
Hi. Have just finished reading "Java EE 6 Cookbook for Securing, Tuning, and Extending Enterprise Applications".
A good book to scratch the surface from the J2EE development. It gives you an overview of J2EE 6 and gives you direction to further investigation. The cons of this book are a tutorial style which describes how to do something in different containers. In my opinion this information can be obtained from the documentation to that containers.
A good book to scratch the surface from the J2EE development. It gives you an overview of J2EE 6 and gives you direction to further investigation. The cons of this book are a tutorial style which describes how to do something in different containers. In my opinion this information can be obtained from the documentation to that containers.
четверг, 28 марта 2013 г.
Tricky Swagger
Hello.
I was faced with a task to create a documentation for our new developing REST service. Search revealed two technologies at hand: JSON-WSP and Swagger.
I liked more Swagger, because:
1) I can dynamically define documentation with annotations in java
2) relatively simple syntax allows to define the documentation by hand
3) there is a good application Swagger UI which allows to explore the service documentation and more important play with your api.
So here are some tricky moments I was faced during the development of specification and using Swagger UI:
1) If you use Swagger UI with documents other than English then you have to insert into Swagger UI index file the meta 'Content-Type' tag.
2) For your convenience set the 'discoveryUrl' in Swagger UI to your resource listing file.
3) When developing the documentation by hand check your json with validators like http://jsonlint.com/. Because errors in Swagger UI are not displayed.
4) When defining parameters in spec you can use
5) When defining you api you should point out the 'responseClass'. If you want your method to return an array of objects you can use the following construction: responseClass: 'List[Item]', where Item is your domain model. This moment is not well documented in documentation.
That's all for now.
I was faced with a task to create a documentation for our new developing REST service. Search revealed two technologies at hand: JSON-WSP and Swagger.
I liked more Swagger, because:
1) I can dynamically define documentation with annotations in java
2) relatively simple syntax allows to define the documentation by hand
3) there is a good application Swagger UI which allows to explore the service documentation and more important play with your api.
So here are some tricky moments I was faced during the development of specification and using Swagger UI:
1) If you use Swagger UI with documents other than English then you have to insert into Swagger UI index file the meta 'Content-Type' tag.
2) For your convenience set the 'discoveryUrl' in Swagger UI to your resource listing file.
3) When developing the documentation by hand check your json with validators like http://jsonlint.com/. Because errors in Swagger UI are not displayed.
4) When defining parameters in spec you can use
path, query, body, or header AND form. The latter allows you to send json into multipart request. The 'form' argument is not mentioned in https://github.com/wordnik/swagger-core/wiki/Parameters.5) When defining you api you should point out the 'responseClass'. If you want your method to return an array of objects you can use the following construction: responseClass: 'List[Item]', where Item is your domain model. This moment is not well documented in documentation.
That's all for now.
четверг, 27 декабря 2012 г.
Make friends: Apache CXF client + WSS4J + CryptoPro
Many of you who worked with government webservices know that the information passed to the service should be signed with GOST algorithm. This leads to the use of CryptoPro library. So here is the interesting part. What I have:
Then, configure the crypto.properties file for wss4j: org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=HDImageStore
org.apache.ws.security.crypto.merlin.keystore.password=1234567890
org.apache.ws.security.crypto.merlin.keystore.alias=tester
org.apache.ws.security.crypto.merlin.keystore.file=c:/cert.store
Then, configure your client:
Here is the example of client:
For this to work I had to patch WSS4j. Download the sources for WSS4j 1.6.6 and edit the file org.apache.ws.security.message.WSSecSignature.java. Find the init method and replace it with this code:
Compile the file and add the compiled class to the wss4j jar.
After this, I could successfully run the client.
- jdk 1.6.0.38 + JCP CryptoPro
- ready to use keystore
- wss4j 1.6.6
- apache cxf 2.6.1
- XMLDSigRI.jar
Then, configure the crypto.properties file for wss4j: org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=HDImageStore
org.apache.ws.security.crypto.merlin.keystore.password=1234567890
org.apache.ws.security.crypto.merlin.keystore.alias=tester
org.apache.ws.security.crypto.merlin.keystore.file=c:/cert.store
Then, configure your client:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <!-- The SOAP client bean --> <jaxws:client id="client" serviceClass="ru.my.IService" address="http://test/IService/IdentificationService.svc"> <jaxws:inInterceptors> <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"/> </jaxws:inInterceptors> <jaxws:outInterceptors> <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"/> <ref bean="wss4jOutConfiguration" /> </jaxws:outInterceptors> </jaxws:client> <bean id="wss4jOutConfiguration" class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor"> <property name="properties"> <map> <entry key="action" value="Signature"/> <entry key="signaturePropFile" value="crypto.properties"/> <entry key="signatureKeyIdentifier" value="DirectReference"/> <entry key="user" value="tester"/> <entry key="signatureUser" value="tester"/> <entry key="passwordCallbackClass" value="ru.client.KeystorePasswordCallback"></entry> <entry key="signatureDigestAlgorithm" value="http://www.w3.org/2001/04/xmldsig-more#gostr3411"/> <entry key="signatureAlgorithm" value="http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411"/> </map> </property> </bean> </beans>Everything seems good, but your client won't work.
Here is the example of client:
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
ru.IService client = (ru.IService) context.getBean("client");
ru.CryptoPro.JCPxml.XmlInit.init();
if(!JCPXMLDSigInit.isInitialized()){
JCPXMLDSigInit.init();
}
Result res = client.callMethod(123);
For this to work I had to patch WSS4j. Download the sources for WSS4j 1.6.6 and edit the file org.apache.ws.security.message.WSSecSignature.java. Find the init method and replace it with this code:
private void init() {
Provider xmlDSigProvider = new ru.CryptoPro.JCPxml.dsig.internal.dom.XMLDSigRI();
signatureFactory = XMLSignatureFactory.getInstance("DOM", xmlDSigProvider);//XMLSignatureFactory.getInstance("DOM");
keyInfoFactory = KeyInfoFactory.getInstance("DOM", xmlDSigProvider);
}
Compile the file and add the compiled class to the wss4j jar.
After this, I could successfully run the client.
воскресенье, 9 сентября 2012 г.
Spring + MongoDb. Первое знакомство.
В одном из моих проектов мне понадобилось использовать mongodb в качестве хранилища данных сессии пользователя.
Для работы на java с mongodb можно использовать java драйвер. Это довольно утомительное занятие. Поэтому я нашёл интересный проект spring-data-mongodb, который позволяет упростить работу с mongodb.
Для работы на java с mongodb можно использовать java драйвер. Это довольно утомительное занятие. Поэтому я нашёл интересный проект spring-data-mongodb, который позволяет упростить работу с mongodb.
вторник, 21 августа 2012 г.
Apache cxf 2.6.1 и Eclipse (part 2)
В этой части я решил избавиться от зависимости в виде Eclipse и научиться генерировать веб-сервис с помощью CXF.
суббота, 18 августа 2012 г.
Apache cxf 2.6.1 и Eclipse
В этой заметке мы опишем, как можно с помощью ant в Eclipse создавать веб сервис apache cxf.
понедельник, 13 августа 2012 г.
Ant. Первое знакомство.
Функции Ant:
1) компиляция
2) junit тесты
3) junit отчёты
4) проверка кода на соответствие стилю программирования checkstyle (http://checkstyle.sourceforge.net)
5) создание jar\war файла
6) создания meta-inf файла
7) создание javadoc
8) генерация классов для клиента к веб-сервису с помощью wsdl2java (из пакета apache cxf)
9) выполнение sql скриптов к СУБД
10) установка war файла на сервер приложений, например Tomcat
Можно ли заменить билдер в Eclipse и оставить только ant?
В Eclipse невозможно полностью отключить встроенный builder проекта, поэтому в данном случае исполнение задачи javac не будет иметь смысл.
Состав целей проекта:
default - цель по умолчанию
all - создание дистрибутива и тестирование
clean - удаление всех созданных файлов
dist - создание дистрибутива
docs - создание документации
test - запуск unit тестов
noop - вывод на экран названия проекта
diag - вывод параметров окружения ant.
Управление большими проектами:
С помощью задачи ant можно вызывать цели в других build файлах. Начиная с версии 1.7 появилась задача subant, которая может исполнять build файлы.
суббота, 21 июля 2012 г.
Клиент Spring ws 2.1.0 + http components 4.2.1
В данном заметке я напишу о том, как мне удалось заставить работать связку из Spring ws 2.1.0 и http components 4.2.1.
Итак, начну с конфига:
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<property name="messageSenders">
<list>
<ref bean="httpSender" />
</list>
</property>
</bean>
<!-- http sender configuration -->
<bean id="httpSender" class="org.springframework.ws.transport.http.HttpComponentsMessageSender">
<constructor-arg>
<ref bean="httpClient"/>
</constructor-arg>
</bean>
<!-- http client definition -->
<bean id="httpClient" class="ru.chernykh.MyDefaultHttpClient">
<constructor-arg>
<ref bean="connmanager"/>
</constructor-arg>
<property name="params" ref="httpParams" />
</bean>
<!-- http params definition -->
<bean id="httpParams" class="org.apache.http.params.SyncBasicHttpParams"/>
<!-- setup thread-safe connection manager -->
<bean id="connmanager" class="org.apache.http.impl.conn.PoolingClientConnectionManager" destroy-method="shutdown">
<property name="maxTotal" value="100"></property>
<property name="defaultMaxPerRoute" value="100"></property>
</bean>
<!-- connection manager params -->
<bean id="connParams" class="org.apache.http.params.HttpConnectionParamBean">
<constructor-arg>
<ref bean="httpParams"/>
</constructor-arg>
<property name="soTimeout" value="10000"></property>
</bean>
Здесь всё стандартно за исключением бина httpClient. По умолчанию, если мы будем использовать DefaultHttpClient, то получим ошибку исполнения:
"Content-Length header already present". Это означает, что httpclient пытается поставить заголовок в надежде что его нет, но это не так, поэтому получаем исключение.
Класс ru.chernykh.MyDefaultHttpClient выглядит так:
public class MyDefaultHttpClient extends DefaultHttpClient{
protected BasicHttpProcessor createHttpProcessor() {
BasicHttpProcessor processor = super.createHttpProcessor();
processor.addInterceptor(new RemoveHttpHeadersInterceptor(), 0);
return processor;
}
public MyDefaultHttpClient(org.apache.http.impl.conn.PoolingClientConnectionManager connManager){
super(connManager);
}
}
А класс RemoveHttpHeadersInterceptor следующим образом:
public class RemoveHttpHeadersInterceptor implements HttpRequestInterceptor{
public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
if (request instanceof HttpEntityEnclosingRequest) {
if (request.containsHeader(HTTP.TRANSFER_ENCODING)) {
request.removeHeaders(HTTP.TRANSFER_ENCODING);
}
if (request.containsHeader(HTTP.CONTENT_LEN)) {
request.removeHeaders(HTTP.CONTENT_LEN);
}
}
}
}
После этого, клиент заработал, и ошибок не было.
Хочу обратить внимание, что по умолчанию в классе
org.springframework.ws.transport.http.HttpComponentsMessageSender используется deprecated API http components(рекомендую взглянуть в исходниках). Поэтому лучше потратить время на ручную установку параметров httpClient, как это сделал я.
Итак, начну с конфига:
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<property name="messageSenders">
<list>
<ref bean="httpSender" />
</list>
</property>
</bean>
<!-- http sender configuration -->
<bean id="httpSender" class="org.springframework.ws.transport.http.HttpComponentsMessageSender">
<constructor-arg>
<ref bean="httpClient"/>
</constructor-arg>
</bean>
<!-- http client definition -->
<bean id="httpClient" class="ru.chernykh.MyDefaultHttpClient">
<constructor-arg>
<ref bean="connmanager"/>
</constructor-arg>
<property name="params" ref="httpParams" />
</bean>
<!-- http params definition -->
<bean id="httpParams" class="org.apache.http.params.SyncBasicHttpParams"/>
<!-- setup thread-safe connection manager -->
<bean id="connmanager" class="org.apache.http.impl.conn.PoolingClientConnectionManager" destroy-method="shutdown">
<property name="maxTotal" value="100"></property>
<property name="defaultMaxPerRoute" value="100"></property>
</bean>
<!-- connection manager params -->
<bean id="connParams" class="org.apache.http.params.HttpConnectionParamBean">
<constructor-arg>
<ref bean="httpParams"/>
</constructor-arg>
<property name="soTimeout" value="10000"></property>
</bean>
Здесь всё стандартно за исключением бина httpClient. По умолчанию, если мы будем использовать DefaultHttpClient, то получим ошибку исполнения:
"Content-Length header already present". Это означает, что httpclient пытается поставить заголовок в надежде что его нет, но это не так, поэтому получаем исключение.
Класс ru.chernykh.MyDefaultHttpClient выглядит так:
public class MyDefaultHttpClient extends DefaultHttpClient{
protected BasicHttpProcessor createHttpProcessor() {
BasicHttpProcessor processor = super.createHttpProcessor();
processor.addInterceptor(new RemoveHttpHeadersInterceptor(), 0);
return processor;
}
public MyDefaultHttpClient(org.apache.http.impl.conn.PoolingClientConnectionManager connManager){
super(connManager);
}
}
А класс RemoveHttpHeadersInterceptor следующим образом:
public class RemoveHttpHeadersInterceptor implements HttpRequestInterceptor{
public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
if (request instanceof HttpEntityEnclosingRequest) {
if (request.containsHeader(HTTP.TRANSFER_ENCODING)) {
request.removeHeaders(HTTP.TRANSFER_ENCODING);
}
if (request.containsHeader(HTTP.CONTENT_LEN)) {
request.removeHeaders(HTTP.CONTENT_LEN);
}
}
}
}
После этого, клиент заработал, и ошибок не было.
Хочу обратить внимание, что по умолчанию в классе
org.springframework.ws.transport.http.HttpComponentsMessageSender используется deprecated API http components(рекомендую взглянуть в исходниках). Поэтому лучше потратить время на ручную установку параметров httpClient, как это сделал я.
пятница, 6 июля 2012 г.
Пример клиента на Spring Web Service
Итак, вызов веб-сервиса выглядит следующим образом:
В данном случае я отсылаю запрос в виде строки и принимаю обратно строку.
Основным классом, выполняющим грязную работу, является WebServiceTemplate.
При этом создание экземпляра этого класса можно сделать так:
Всё просто, не правда ли?
Правда, если мы хотим выставить таймаут на ожидание выполнения запроса, то необходимо в проект добавить библиотеку http commons 3.1.1 и изменить определение бина следующим образом:
Счастливой пятницы!
UPD 2012-07-14: Наткнулся на проблему, что по умолчанию
/**
* Вызов веб-сервиса
* @param request
* @return
*/
public String invove(String request){
StreamSource source = new StreamSource(new StringReader(request));
ByteArrayOutputStream output = new ByteArrayOutputStream();
StreamResult result = new StreamResult(output);
webServiceTemplate.sendSourceAndReceiveToResult(url, source, result);
String resultStr = "";
try {
resultStr = new String(output.toByteArray(), "UTF-8");
} catch (UnsupportMultiThreadedHttpConnectionManageredEncodingException e) {
logger.error(e.getMessage(), e);
}
return resultStr;
}
В данном случае я отсылаю запрос в виде строки и принимаю обратно строку.
Основным классом, выполняющим грязную работу, является WebServiceTemplate.
При этом создание экземпляра этого класса можно сделать так:
Всё просто, не правда ли?
Правда, если мы хотим выставить таймаут на ожидание выполнения запроса, то необходимо в проект добавить библиотеку http commons 3.1.1 и изменить определение бина следующим образом:
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<property name="messageSenders">
<list>
<ref bean="httpSender" />
</list>
</property>
</bean>
<!-- add for thread safety -->
<bean id="connmanager" class="org.apache.commons.httpclient.MultiThreadedHttpConnectionManager">
<property name="params" ref="connmanagerParams"/>
</bean>
<!-- Total to 300 connections -->
<bean id="connmanagerParams" class="org.apache.commons.httpclient.params.HttpConnectionManagerParams">
<property name="maxTotalConnections" value="300"/>
</bean>
<bean id="httpParams" class="org.apache.commons.httpclient.params.HttpClientParams">
<!-- Timeout in milliseconds: in this case 10 seconds -->
<property name="soTimeout" value="10000" />
</bean>
<bean id="httpClient" class="org.apache.commons.httpclient.HttpClient">
<property name="params" ref="httpParams" />
<property name="httpConnectionManager" ref="connmanager"/>
</bean>
<bean id="httpSender" class="org.springframework.ws.transport.http.CommonsHttpMessageSender">
<constructor-arg>
<ref bean="httpClient"/>
</constructor-arg>
</bean>
Счастливой пятницы!
UPD 2012-07-14: Наткнулся на проблему, что по умолчанию
org.apache.commons.httpclient.HttpClient
не безопасен для использования в многопоточной среде. Чтобы это исправить, необходимо HttpClient передатьэкземплярMultiThreadedHttpConnectionManager
После этого Commons Http должен работать корректно в заданной конфигурации.
среда, 4 июля 2012 г.
Мысли о фреймворках java
Выдалось время подумать о том, как можно улучшить написание богатых приложений, работающих в браузере. Сразу приходит в голову множество разных фреймворков:
Первое с чего начинают разработчики это jsp + sertvlet + jstl. Это сравни ассемблеру. Идея хорошая. Реализация простая и надёжная. Однако богатые приложения на такой связке быстро не создашь.
Struts в этом плане лучше. Есть поддержка валидации, описание правил перехода по страницам. Богатые приложения на такой связке быстро не создашь.
JSF. Пожалуй, единственным плюсом данного каркаса является то, что он входит в J2EE с версии 5. Эта библиотека максимум для чего подходит - быстрое прототипирование приложений. Кроме того, если разработчику дали вёрстку и сказали использовать её в JSF приложении, то это будет геморрой. А если потом эту jsf страничку понадобится модифицировать верстальщику, то верстальщик в этих jsf компонентах ничего не поймёт.
Существует большое количество jsf библиотек. Каждая со своими глюками и компонентами. Поэтому, кроме головной боли, эта библиотека в продуктивных системах ничего более не принесёт.
Gwt. Приложения, которые создаются на этой библиотеке поистине богаты.
Apache click. Утверждается, что это отличная библиотека для богатых приложений, не занимающихся работой с хранением состояния.
Apache wicket. Это библиотека ориентирована на создание богатых приложений, которые часто и много имеют дело с хранением состояния приложения. Как утверждается на сайте библиотеки, в ней решена проблема кнопки Back в браузерах. Пожалуй, стоит уделить немного внимания данной библиотеке.
Spring mvc. Эта библиотека сделана разработчиками spring. Сам я дела с ней не имел и отзывов никаких не слышал. Поэтому упомянул её здесь для галочки.
- jsf/myfaces + facelets
- struts
- jsp+servlet+jstl, возможно tiles
- gwt
- apache click
- apache wicket
- spring mvc
Первое с чего начинают разработчики это jsp + sertvlet + jstl. Это сравни ассемблеру. Идея хорошая. Реализация простая и надёжная. Однако богатые приложения на такой связке быстро не создашь.
Struts в этом плане лучше. Есть поддержка валидации, описание правил перехода по страницам. Богатые приложения на такой связке быстро не создашь.
JSF. Пожалуй, единственным плюсом данного каркаса является то, что он входит в J2EE с версии 5. Эта библиотека максимум для чего подходит - быстрое прототипирование приложений. Кроме того, если разработчику дали вёрстку и сказали использовать её в JSF приложении, то это будет геморрой. А если потом эту jsf страничку понадобится модифицировать верстальщику, то верстальщик в этих jsf компонентах ничего не поймёт.
Существует большое количество jsf библиотек. Каждая со своими глюками и компонентами. Поэтому, кроме головной боли, эта библиотека в продуктивных системах ничего более не принесёт.
Gwt. Приложения, которые создаются на этой библиотеке поистине богаты.
Apache click. Утверждается, что это отличная библиотека для богатых приложений, не занимающихся работой с хранением состояния.
Apache wicket. Это библиотека ориентирована на создание богатых приложений, которые часто и много имеют дело с хранением состояния приложения. Как утверждается на сайте библиотеки, в ней решена проблема кнопки Back в браузерах. Пожалуй, стоит уделить немного внимания данной библиотеке.
Spring mvc. Эта библиотека сделана разработчиками spring. Сам я дела с ней не имел и отзывов никаких не слышал. Поэтому упомянул её здесь для галочки.
суббота, 30 июня 2012 г.
Установка tomcat6 на linux mint 13
Установить пакеты:
tomcat6-user
libtomcat6-java
tomcat6-common
tomcat6-admin
tomcat6-docs
Далее вызываем man tomcat6-instance-create и внимательно изучаем то, что нам предлагается.
Эта команда позволяет нам создать свой экземпляр Tomcat. Формат команды tomcat6-instance-create опции имя_каталога.
Каталог не должен существовать. Он будет создан автоматически.
В качестве опций нам предлагаются следующие:
-p HTTPPORT - порт, на котором будет жить наш экземпляр tomcat. По умолчанию 8080.
-c CONTROLPORT - порт, по которому можно будет остановить tomcat. По умолчанию 8005.
-w MAGICWORD - магическое слово, которое необходимо послать на CONTROLPORT для останова сервиса. По умолчанию SHUTDOWN.
Создадим экземпляр с помощью команды tomcat6-instance-create ~/tomcatinst1.
You are about to create a Tomcat instance in directory '/home/duglas/tomcatint1'
* New Tomcat instance created in /home/duglas/tomcatint1
* You might want to edit default configuration in /home/duglas/tomcatint1/conf
* Run /home/duglas/tomcatint1/bin/startup.sh to start your Tomcat instance
Теперь у нас есть свой экземпляр tomcat, с которым можно работать.
Открываем файл cont/tomcat-users.xml и добавляем строчки
<role rolename="manager"/>
<role rolename="tomcat"/>
<role rolename="role1"/>
<user username="admin" password="admin" roles="tomcat,manager"/>
<user username="tomcat" password="tomcat" roles="tomcat"/>
<user username="both" password="tomcat" roles="tomcat,role1"/>
<user username="role1" password="tomcat" roles="role1"/>
Переходим в каталог bin и запускаем tomcat ./startup.sh:
Using CATALINA_BASE: /home/duglas/tomcatint1
Using CATALINA_HOME: /usr/share/tomcat6
Using CATALINA_TMPDIR: /home/duglas/tomcatint1/temp
Using JRE_HOME: /usr/lib/jvm/java-6-openjdk
Using CLASSPATH: /usr/share/tomcat6/bin/bootstrap.jar
Tomcat started
Набрав в строке браузера http://localhost:8080, откроется пустая страница.
Пакет с документацией ставится в каталог /usr/share/tomcat6-docs/docs.
Приложение для развёртывания приложений находится в каталоге /usr/share/tomcat6-admin.
Для того, чтобы это приложение заработало, необходимо скопировать каталог tomcat6-admin в каталог webapps нашего экземпляра Tomcat и перезапустить Tomcat. Далее, это приложение будет доступно по адресу http://localhost:8080/manager/html.
tomcat6-user
libtomcat6-java
tomcat6-common
tomcat6-admin
tomcat6-docs
Далее вызываем man tomcat6-instance-create и внимательно изучаем то, что нам предлагается.
Эта команда позволяет нам создать свой экземпляр Tomcat. Формат команды tomcat6-instance-create опции имя_каталога.
Каталог не должен существовать. Он будет создан автоматически.
В качестве опций нам предлагаются следующие:
-p HTTPPORT - порт, на котором будет жить наш экземпляр tomcat. По умолчанию 8080.
-c CONTROLPORT - порт, по которому можно будет остановить tomcat. По умолчанию 8005.
-w MAGICWORD - магическое слово, которое необходимо послать на CONTROLPORT для останова сервиса. По умолчанию SHUTDOWN.
Создадим экземпляр с помощью команды tomcat6-instance-create ~/tomcatinst1.
You are about to create a Tomcat instance in directory '/home/duglas/tomcatint1'
* New Tomcat instance created in /home/duglas/tomcatint1
* You might want to edit default configuration in /home/duglas/tomcatint1/conf
* Run /home/duglas/tomcatint1/bin/startup.sh to start your Tomcat instance
Теперь у нас есть свой экземпляр tomcat, с которым можно работать.
Открываем файл cont/tomcat-users.xml и добавляем строчки
<role rolename="manager"/>
<role rolename="tomcat"/>
<role rolename="role1"/>
<user username="admin" password="admin" roles="tomcat,manager"/>
<user username="tomcat" password="tomcat" roles="tomcat"/>
<user username="both" password="tomcat" roles="tomcat,role1"/>
<user username="role1" password="tomcat" roles="role1"/>
Переходим в каталог bin и запускаем tomcat ./startup.sh:
Using CATALINA_BASE: /home/duglas/tomcatint1
Using CATALINA_HOME: /usr/share/tomcat6
Using CATALINA_TMPDIR: /home/duglas/tomcatint1/temp
Using JRE_HOME: /usr/lib/jvm/java-6-openjdk
Using CLASSPATH: /usr/share/tomcat6/bin/bootstrap.jar
Tomcat started
Набрав в строке браузера http://localhost:8080, откроется пустая страница.
Пакет с документацией ставится в каталог /usr/share/tomcat6-docs/docs.
Приложение для развёртывания приложений находится в каталоге /usr/share/tomcat6-admin.
Для того, чтобы это приложение заработало, необходимо скопировать каталог tomcat6-admin в каталог webapps нашего экземпляра Tomcat и перезапустить Tomcat. Далее, это приложение будет доступно по адресу http://localhost:8080/manager/html.
суббота, 12 мая 2012 г.
FreeMarker. Продолжение.
Сегодня почти весь день убил на то, чтобы справиться с проблемой: на рабочей станции в среде разработки FreeMarker отлично считывает и заполняет шаблон.
Как только я ставлю портлет на сервер, то на выходе я получаю пустой шаблон! В логах никаких ошибок, включение логов в режим DEBUG тоже ничего дало - FreeMarker находит мой шаблон, но на выходе отдаёт пустой текст. Детальное исследование показало, что FreeMarker считывает шаблон пустым. Додумался проверить кодировку текста шаблона - формально файл был закодирован в UTF-8, но видимо при просмотре или редактировании шаблона кодировка слетела. После приведения файла в UTF-8 мой шаблон заработал на сервере!
Жаль потраченного времени, но зато это помогло мне разобраться получше в API FreeMarker.
Как только я ставлю портлет на сервер, то на выходе я получаю пустой шаблон! В логах никаких ошибок, включение логов в режим DEBUG тоже ничего дало - FreeMarker находит мой шаблон, но на выходе отдаёт пустой текст. Детальное исследование показало, что FreeMarker считывает шаблон пустым. Додумался проверить кодировку текста шаблона - формально файл был закодирован в UTF-8, но видимо при просмотре или редактировании шаблона кодировка слетела. После приведения файла в UTF-8 мой шаблон заработал на сервере!
Жаль потраченного времени, но зато это помогло мне разобраться получше в API FreeMarker.
пятница, 11 мая 2012 г.
FreeMarker
Возникла у меня задача: есть в наличии html шаблон, который надо заполнять данными и отправлять на e-mail. Сначала я подумал, а почему не забить шаблон в код? И как потом поддерживать получившееся Г?
Следующей мыслью было - вынести шаблон в отдельный файл. Это уже лучше. Но возникает следующая проблема - нужно придумывать свой язык для обозначения позиций, где необходимо осуществить подстановку. Поэтому это мысль тоже отпала.
В результате поисков выбор пал на библиотеку FreeMarker (http://freemarker.sourceforge.net/). Библиотека занимает почти 1 мегабайт. Поддерживает java 1.2 и выше. Библиотека является мощным движком для генерации текста по шаблону.
Поддерживает вычисления внутри шаблоне. Надо сказать, что вычисления осуществляются через BigDecimal. Поддерживаются директивы.
Также есть сносная документация, которая описывает все плюшки более подробно.
Конкурентом этой библиотеки является Apache Velocity. Опыта работы с этой библиотекой не было, но судя по форумам народ от неё не в сильном восторге.
Следующей мыслью было - вынести шаблон в отдельный файл. Это уже лучше. Но возникает следующая проблема - нужно придумывать свой язык для обозначения позиций, где необходимо осуществить подстановку. Поэтому это мысль тоже отпала.
В результате поисков выбор пал на библиотеку FreeMarker (http://freemarker.sourceforge.net/). Библиотека занимает почти 1 мегабайт. Поддерживает java 1.2 и выше. Библиотека является мощным движком для генерации текста по шаблону.
Поддерживает вычисления внутри шаблоне. Надо сказать, что вычисления осуществляются через BigDecimal. Поддерживаются директивы.
Также есть сносная документация, которая описывает все плюшки более подробно.
Конкурентом этой библиотеки является Apache Velocity. Опыта работы с этой библиотекой не было, но судя по форумам народ от неё не в сильном восторге.
понедельник, 5 марта 2012 г.
OpenJDK 1.7.0 на NetBSD
В этой небольшой заметке я расскажу как установить jdk 1.7 на NetBSD 5.1.2.
Войдём как root.
Далее cd /usr/pkgsrc/lang/openjd7.
make install && clean && clean-depends.
Java установится по пути /usr/pkg/java/openjdk7.
Полёт нормальный.
Войдём как root.
Далее cd /usr/pkgsrc/lang/openjd7.
make install && clean && clean-depends.
Java установится по пути /usr/pkg/java/openjdk7.
Полёт нормальный.
Подписаться на:
Сообщения (Atom)