Наиболее достоверную информацию о сессия приложения можно получить непосредственно из консоли WLST
17.04.2019
23.07.2018
Анмаршаллинг XML в класс при помощи JAXB
public JAXBElement processFile(File file){
Class clazz = SomePojo.class;
JAXBElement jaxbElement = null;
try {
JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
jaxbElement = unmarshaller.unmarshal(new StreamSource(file), clazz);
} catch (Exception e) {
e.printStackTrace();
}
return jaxbElement;
}
27.04.2017
Список полей через java reflection
private List getElementMetadata(Class clazz){ List<Field> list = new ArrayList<>(); if (clazz.getSuperclass() != null && !clazz.getSuperclass().equals(Object.class)) { List<Field> sublist = getElementMetadata(clazz.getSuperclass()); for(Field field : sublist){ list.add(field); } } Field fields[] = clazz.getDeclaredFields(); for(Field field : fields){ list.add(field); } return list; }
05.12.2016
Установка и настройка Wildfly 10 под Debian 7
Прошел интересный квест по установке Wildfly 10 на Debian 7 с последующим созданием Data Source к базе Oracle 11g. Поехали.
0. Скрипт установки.
- создаем каталог $WILDFLY_HOME/modules/system/layers/base/com/oracle/ojdbc6/main/ (того, что подчеркнуто, в системе не было)
- заливаем в main собственно драйвер ojdbc6.jar и там же создаем файл module.xml следующего содержания:
2. Регистрируем драйвер:
3. Конфигурация датасорса в standalone.xml после выполнения всех операций:
0. Скрипт установки.
#!/bin/bash
WILDFLY_VERSION=10.0.0.Final
WILDFLY_FILENAME=wildfly-$WILDFLY_VERSION
WILDFLY_ARCHIVE_NAME=$WILDFLY_FILENAME.tar.gz
WILDFLY_DOWNLOAD_ADDRESS=http://download.jboss.org/wildfly/$WILDFLY_VERSION/$WILDFLY_ARCHIVE_NAME
INSTALL_DIR=/opt
WILDFLY_FULL_DIR=$INSTALL_DIR/$WILDFLY_FILENAME
WILDFLY_DIR=$INSTALL_DIR/wildfly
WILDFLY_USER="wildfly"
WILDFLY_SERVICE="wildfly"
WILDFLY_MODE="standalone"
WILDFLY_STARTUP_TIMEOUT=240
WILDFLY_SHUTDOWN_TIMEOUT=30
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root."
exit 1
fi
echo "Downloading: $WILDFLY_DOWNLOAD_ADDRESS..."
[ -e "$WILDFLY_ARCHIVE_NAME" ] && echo 'Wildfly archive already exists.'
if [ ! -e "$WILDFLY_ARCHIVE_NAME" ]; then
wget -q $WILDFLY_DOWNLOAD_ADDRESS
if [ $? -ne 0 ]; then
echo "Not possible to download Wildfly."
exit 1
fi
fi
echo "Cleaning up..."
rm -f "$WILDFLY_DIR"
rm -rf "$WILDFLY_FULL_DIR"
rm -rf "/var/run/$WILDFLY_SERVICE/"
rm -f "/etc/init.d/$WILDFLY_SERVICE"
echo "Installation..."
mkdir $WILDFLY_FULL_DIR
tar -xzf $WILDFLY_ARCHIVE_NAME -C $INSTALL_DIR
ln -s $WILDFLY_FULL_DIR/ $WILDFLY_DIR
useradd -s /sbin/nologin $WILDFLY_USER
chown -R $WILDFLY_USER:$WILDFLY_USER $WILDFLY_DIR
chown -R $WILDFLY_USER:$WILDFLY_USER $WILDFLY_DIR/
#mkdir -p /var/log/$WILDFLY_SERVICE
echo "Registrating Wildfly as service..."
# if should use systemd
if [ -x /bin/systemctl ]; then
# Script from $WILDFLY_DIR/docs/contrib/scripts/systemd/launch.sh didn't work for me
cat > $WILDFLY_DIR/bin/launch.sh << "EOF"
#!/bin/sh
if [ "x$WILDFLY_HOME" = "x" ]; then
WILDFLY_HOME="/opt/wildfly"
fi
if [ "x$1" = "xdomain" ]; then
echo 'Starting Wildfly in domain mode.'
$WILDFLY_HOME/bin/domain.sh -c $2 -b $3
#>> /var/log/$WILDFLY_SERVICE/server-`date +%Y-%m-%d`.log
else
echo 'Starting Wildfly in standalone mode.'
$WILDFLY_HOME/bin/standalone.sh -c $2 -b $3
#>> /var/log/$WILDFLY_SERVICE/server-`date +%Y-%m-%d`.log
fi
EOF
# $WILDFLY_HOME is not visible here
sed -i -e 's,WILDFLY_HOME=.*,WILDFLY_HOME='$WILDFLY_DIR',g' $WILDFLY_DIR/bin/launch.sh
#sed -i -e 's,$WILDFLY_SERVICE,'$WILDFLY_SERVICE',g' $WILDFLY_DIR/bin/launch.sh
chmod +x $WILDFLY_DIR/bin/launch.sh
cp $WILDFLY_DIR/docs/contrib/scripts/systemd/wildfly.service /etc/systemd/system/$WILDFLY_SERVICE.service
WILDFLY_SERVICE_CONF=/etc/default/$WILDFLY_SERVICE
# To install multiple instances of Wildfly replace all hardcoding in systemd file
sed -i -e 's,EnvironmentFile=.*,EnvironmentFile='$WILDFLY_SERVICE_CONF',g' /etc/systemd/system/$WILDFLY_SERVICE.service
sed -i -e 's,User=.*,User='$WILDFLY_USER',g' /etc/systemd/system/$WILDFLY_SERVICE.service
sed -i -e 's,PIDFile=.*,PIDFile=/var/run/wildfly/'$WILDFLY_SERVICE'.pid,g' /etc/systemd/system/$WILDFLY_SERVICE.service
sed -i -e 's,ExecStart=.*,ExecStart='$WILDFLY_DIR'/bin/launch.sh $WILDFLY_MODE $WILDFLY_CONFIG $WILDFLY_BIND,g' /etc/systemd/system/$WILDFLY_SERVICE.service
systemctl daemon-reload
#systemctl enable $WILDFLY_SERVICE.service
fi
# if non-systemd Debian-like distribution
if [ ! -x /bin/systemctl -a -r /lib/lsb/init-functions ]; then
cp $WILDFLY_DIR/docs/contrib/scripts/init.d/wildfly-init-debian.sh /etc/init.d/$WILDFLY_SERVICE
sed -i -e 's,NAME=wildfly,NAME='$WILDFLY_SERVICE',g' /etc/init.d/$WILDFLY_SERVICE
WILDFLY_SERVICE_CONF=/etc/default/$WILDFLY_SERVICE
fi
# if non-systemd RHEL-like distribution
if [ ! -x /bin/systemctl -a -r /etc/init.d/functions ]; then
cp $WILDFLY_DIR/docs/contrib/scripts/init.d/wildfly-init-redhat.sh /etc/init.d/$WILDFLY_SERVICE
WILDFLY_SERVICE_CONF=/etc/default/wildfly.conf
chmod 755 /etc/init.d/$WILDFLY_SERVICE
fi
# if neither Debian nor RHEL like distribution
if [ ! -x /bin/systemctl -a ! -r /lib/lsb/init-functions -a ! -r /etc/init.d/functions ]; then
cat > /etc/init.d/$WILDFLY_SERVICE << "EOF"
#!/bin/sh
### BEGIN INIT INFO
# Provides: ${WILDFLY_SERVICE}
# Required-Start: $local_fs $remote_fs $network $syslog
# Required-Stop: $local_fs $remote_fs $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start/Stop ${WILDFLY_FILENAME}
### END INIT INFO
WILDFLY_USER=${WILDFLY_USER}
WILDFLY_DIR=${WILDFLY_DIR}
case "$1" in
start)
echo "Starting ${WILDFLY_FILENAME}..."
start-stop-daemon --start --background --chuid $WILDFLY_USER --exec $WILDFLY_DIR/bin/standalone.sh
exit $?
;;
stop)
echo "Stopping ${WILDFLY_FILENAME}..."
start-stop-daemon --start --quiet --background --chuid $WILDFLY_USER --exec $WILDFLY_DIR/bin/jboss-cli.sh -- --connect command=:shutdown
exit $?
;;
log)
echo "Showing server.log..."
tail -500f $WILDFLY_DIR/standalone/log/server.log
;;
*)
echo "Usage: /etc/init.d/wildfly {start|stop}"
exit 1
;;
esac
exit 0
EOF
sed -i -e 's,${WILDFLY_USER},'$WILDFLY_USER',g; s,${WILDFLY_FILENAME},'$WILDFLY_FILENAME',g; s,${WILDFLY_SERVICE},'$WILDFLY_SERVICE',g; s,${WILDFLY_DIR},'$WILDFLY_DIR',g' /etc/init.d/$WILDFLY_SERVICE
chmod 755 /etc/init.d/$WILDFLY_SERVICE
fi
if [ ! -z "$WILDFLY_SERVICE_CONF" ]; then
echo "Configuring service..."
echo JBOSS_HOME=\"$WILDFLY_DIR\" > $WILDFLY_SERVICE_CONF
echo JBOSS_USER=$WILDFLY_USER >> $WILDFLY_SERVICE_CONF
echo WILDFLY_HOME=\"$WILDFLY_DIR\" > $WILDFLY_SERVICE_CONF
echo WILDFLY_USER=\"$WILDFLY_USER\" > $WILDFLY_SERVICE_CONF
echo STARTUP_WAIT=$WILDFLY_STARTUP_TIMEOUT >> $WILDFLY_SERVICE_CONF
echo SHUTDOWN_WAIT=$WILDFLY_SHUTDOWN_TIMEOUT >> $WILDFLY_SERVICE_CONF
echo WILDFLY_CONFIG=$WILDFLY_MODE.xml >> $WILDFLY_SERVICE_CONF
echo WILDFLY_MODE=$WILDFLY_MODE >> $WILDFLY_SERVICE_CONF
echo WILDFLY_BIND=0.0.0.0 >> $WILDFLY_SERVICE_CONF
fi
echo "Configuring application server..."
sed -i -e 's,<deployment-scanner path="deployments" relative-to="jboss.server.base.dir" scan-interval="5000",<deployment-scanner path="deployments" relative-to="jboss.server.base.dir" scan-interval="5000" deployment-timeout="'$WILDFLY_STARTUP_TIMEOUT'",g' $WILDFLY_DIR/$WILDFLY_MODE/configuration/$WILDFLY_MODE.xml
sed -i -e 's,<inet-address value="${jboss.bind.address:127.0.0.1}"/>,<any-address/>,g' $WILDFLY_DIR/$WILDFLY_MODE/configuration/$WILDFLY_MODE.xml
sed -i -e 's,<socket-binding name="ajp" port="${jboss.ajp.port:8009}"/>,<socket-binding name="ajp" port="${jboss.ajp.port:28009}"/>,g' $WILDFLY_DIR/$WILDFLY_MODE/configuration/$WILDFLY_MODE.xml
sed -i -e 's,<socket-binding name="http" port="${jboss.http.port:8080}"/>,<socket-binding name="http" port="${jboss.http.port:28080}"/>,g' $WILDFLY_DIR/$WILDFLY_MODE/configuration/$WILDFLY_MODE.xml
sed -i -e 's,<socket-binding name="https" port="${jboss.https.port:8443}"/>,<socket-binding name="https" port="${jboss.https.port:28443}"/>,g' $WILDFLY_DIR/$WILDFLY_MODE/configuration/$WILDFLY_MODE.xml
sed -i -e 's,<socket-binding name="osgi-http" interface="management" port="8090"/>,<socket-binding name="osgi-http" interface="management" port="28090"/>,g' $WILDFLY_DIR/$WILDFLY_MODE/configuration/$WILDFLY_MODE.xml
[ -x /bin/systemctl ] && systemctl start $WILDFLY_SERVICE || service $WILDFLY_SERVICE start
echo "Done."
1. По умолчанию в контейнере нет драйвера JDBC и его надо поставить. Насколько я понимаю, для того, чтобы classloader смог загрузить его, он должен быть объявлен как модуль. По сути, процесс сводится к созданию кастом-модуля и регистрации оного в системе:- создаем каталог $WILDFLY_HOME/modules/system/layers/base/com/oracle/ojdbc6/main/ (того, что подчеркнуто, в системе не было)
- заливаем в main собственно драйвер ojdbc6.jar и там же создаем файл module.xml следующего содержания:
<?xml version="1.0" encoding="UTF-8"?> <module xmlns="urn:jboss:module:1.0" name="com.oracle.ojdbc6"> <resources> <resource-root path="ojdbc6.jar"/> </resources> <dependencies> <module name="javax.api"/> <module name="javax.resource.api"/> <module name="javax.transaction.api"/> </dependencies> </module>
2. Регистрируем драйвер:
root@debian:/opt/wildfly-10.0.0.Final/bin# sh jboss-cli.sh
You are disconnected at the moment. Type 'connect' to connect to the server or 'help' for the list of supported commands.
[disconnected /] connect
[standalone@localhost:9990 /] /subsystem=datasources/jdbc-driver=oracle:add(driver-name=oracle,driver-module-name=com.oracle.ojdbc6,driver-class-name=oracle.jdbc.driver.OracleDriver)
{"outcome" => "success"}
[standalone@localhost:9990 /] exit
root@debian:/opt/wildfly-10.0.0.Final/bin#
3. Конфигурация датасорса в standalone.xml после выполнения всех операций:
<datasource jta="true" jndi-name="java:/OracleDS" pool-name="OracleDS" enabled="true" use-ccm="true"> <connection-url>jdbc:oracle:thin:@####:1521:DEV</connection-url> <driver>oracle</driver> <security> <user-name>admin</user-name> <password>admin</password> </security> <validation> <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleValidConnectionChecker"/> <background-validation>true</background-validation> <stale-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleStaleConnectionChecker"/> <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleExceptionSorter"/> </validation> </datasource>4. После перезагрузки на попытку деплоя любого приожения последует ругань DefaultDataSource is missing [jboss.naming.context.java.jboss.datasources.ExampleDS]. Решается удалением тестового датасорса через терминал JBoss:
# /subsystem=datasources/data-source=ExampleDS:remove() # /subsystem=ee/service=default-bindings:write-attribute(name=datasource,value=undefined)5. Может пригодится предустановленная заглушка security-domain:
<?xml version="1.0" encoding="UTF-8"?> <jboss-web> <context-root>CrudJSF</context-root> <security-domain>jaspitest</security-domain> </jboss-web>
15.09.2016
Модификация запроса View Criteria в runtime
Для того, чтобы модифицировать предикаты, которыми оборачивается запрос из View Criteria, применяется перекрытый метод getCriteriaItemClause класса ViewObjectImpl. Например, мы можем вручную подцепить определеную bind-переменную в произвольное ограничение:
Ещё нюанс о галочке Ignore Null Values с обязательными bind-переменными:
@Override
public String getCriteriaItemClause(ViewCriteriaItem aVCI) {
VariableValueManager vm = this.ensureVariableManager();
ArrayList criteriaList = aVCI.getValues();
for (ViewCriteriaItemValue itemValue : criteriaList) {
if (itemValue.getIsBindVar()) {
Variable bindVariable = itemValue.getBindVariable();
Object variableValue = vm.getVariableValue(bindVariable);
// check for the special DESCRIPTION in the used bind variable
Object descProperty = bindVariable.getProperty("DESCRIPTION");
String description = (descProperty != null ? descProperty.toString() : "null");
if ("NAME".equalsIgnoreCase(description)) {
if (aVCI.getViewCriteria().getRootViewCriteria().isCriteriaForQuery()) {
if (variableValue != null) {
return "EMP.NAME LIKE ('%' || :p_name || '%')";
}
}
}
}
}
return super.getCriteriaItemClause(aVCI);
}
Про происходит: выполняется цикл по всем bind-переменным. Идентификация нужной переменной происходит по свойству DESCRIPTION. Если переменная найдена и она имеет значение, отличное от NULL, добавляется предикат. Иначе вызывается родительский метод.Ещё нюанс о галочке Ignore Null Values с обязательными bind-переменными:
Снятая галочка Ignore Null Values в случае с обязательными bind-переменными обеспечивает оборачивание запроса в ограничение ( = :p_var or :p_var is null) в любом случае, что в случае со сложными запросами может привести к сбиванию плана. Если галочка установлена, то ограничение добавляется только если переменная не NULL.
04.05.2016
Jdeveloper Design Time issue fix
Дополню пост про устранение глюка с отображением страниц в JDeveloper.
Для версии 11.1.2.2.39.61.83.1 нужно удалить следующие каталоги:
Для версии 11.1.2.2.39.61.83.1 нужно удалить следующие каталоги:
- o.jsp.feature
- o.j2ee.jstl
- o.j2ee.jpsconfig
- o.ide.appoverview
- o.j2ee.jsplib
12.02.2016
ADF: кастомный selection-listener и обновление данных в popup
Столкнулся с проблемой: не обновляется отображение переменной биндинга в popup-окне. Решается оборачиванием стандартного листенера в кастомный метод и программным добавлением partial trigger на элемент, инициирующий обновление переменной.
public void customListener(SelectionEvent selectionEvent) {
UIComponent component = selectionEvent.getComponent();
component.processUpdates(FacesContext.getCurrentInstance());
JSFUtils.resolveMethodExpression("#{bindings.AllUsersVO1.collectionModel.makeCurrent}", null,
new Class[]{SelectionEvent.class}, new Object[]{selectionEvent});
setExpressionValueCustom();
}
private void setExpressionValueCustom(){
ViewRowImpl row = (ViewRowImpl)JSFUtils.resolveExpression("#{bindings.AllUsersVO1.currentRow}");
JSFUtils.setExpressionValue("#{bindings.userLogin.inputValue}", row.getAttribute("Username"));
AdfFacesContext.getCurrentInstance().addPartialTarget(getP_delete());
}
getP_delete() - геттер объекта RichPopup.21.01.2016
ADF: Уход со страницы с незафиксированными данными
У концепции ADF есть интересное свойство: обязанность по отслеживанию незакоммиченных данных полностью ложится на программиста. Сложно сказать, как с этим планировалось справляться силами недоучившихся студентов, на которых рассчитано декларативное программирование в ADF. Да и не об этом речь. Речь пойдет о том, как уйти со страницы, которая создала новую запись в VO, связанном c EO, не зафиксировать эту запись, и потом благополучно вернуться обратно.
Что сразу приходит в голову:
Рабочее решение заключается в создании бина уровня приложения, унаследованного от PagePhaseListener, где мы будем анализировать страницу на ранней фазе жизненного цикла и отслеживать грязные данные. Создаем бин и прописываем его в adf-settings.xml:
Сам класс:
Код 9 - id фазы инициализаци Restore View. Интересно проследить жизненный цикл страницы-источника (откуда переходим) после изменения данных:
В целевой странице (куда переходим) грязные данные присутствуют во всем цикле:
Что сразу приходит в голову:
@PostConstruct
public void initBean() {
AppModuleImpl mod = (AppModuleImpl)ADFUtils.getBindingApplicationModule();
DBTransaction conn = mod.getDBTransaction();
if (conn.isDirty()) conn.rollback();
...
Так нехорошо, потому что initBean() будет вызываться при каждой активности на странице и транзакция будет теряться тогда, когда это не нужно. К тому же транзакция будет откатываться на фазе prepareRender, что тоже идеологически неверно. То есть контекст уже проинициализирован, загружена модель данных, проверены валидации, всё готово к прорисовке страницы - и тут мы сообщаем системе, что данные нужно изменить. Не знаю, что именно будет происходить глубоко внутри приложения, но думаю, что ничего хорошего.Рабочее решение заключается в создании бина уровня приложения, унаследованного от PagePhaseListener, где мы будем анализировать страницу на ранней фазе жизненного цикла и отслеживать грязные данные. Создаем бин и прописываем его в adf-settings.xml:
Сам класс:
import java.util.ArrayList;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;
import oracle.adf.controller.v2.lifecycle.PagePhaseEvent;
import oracle.adf.controller.v2.lifecycle.PagePhaseListener;
import oracle.adf.share.ADFContext;
import oracle.jbo.server.DBTransaction;
import *.ADFUtils;
import *.AppModuleImpl;
public class PageListenerBean implements PagePhaseListener{
// если conn.isDirty() и переходим на из url из списка, то rollback
private static String[] deniedUrls = {"/myapp/faces/task-flow-definition/tree"};
@Override
public void beforePhase(PagePhaseEvent pagePhaseEvent) {
try{
if (pagePhaseEvent.getPhaseId() == 9){
AppModuleImpl mod = (AppModuleImpl)ADFUtils.getBindingApplicationModule();
DBTransaction conn = mod.getDBTransaction();
if (isPageChanged()){
if (changedToDisallowed()){
if (conn.isDirty()){
conn.rollback();
System.out.println("= rolled back!");
}
}
}
}
}catch(Exception e){
;
}
}
@Override
public void afterPhase(PagePhaseEvent pagePhaseEvent) {
;
}
private void setApplicationScopeParameter(String val){
ADFContext adfCtx = ADFContext.getCurrent();
Map applicationScope = adfCtx.getApplicationScope();
applicationScope.put("currentURL", val);
}
private String getApplicationScopeParameter(){
ADFContext adfCtx = ADFContext.getCurrent();
Map applicationScope = adfCtx.getApplicationScope();
return (String)applicationScope.get("currentURL");
}
private boolean isPageChanged(){
try{
if (!getCurrentUrl().equals(getApplicationScopeParameter())){
setApplicationScopeParameter(getCurrentUrl());
return true;
}
}catch(NullPointerException e){
System.out.println("--! PageListenerBean: can't get current url");
}
return false;
}
private boolean changedToDisallowed(){
for(String url : this.deniedUrls)
if (url.equals(getCurrentUrl()))
return true;
return false;
}
private String getCurrentUrl(){
FacesContext ctx = FacesContext.getCurrentInstance();
HttpServletRequest servletRequest = (HttpServletRequest) ctx.getExternalContext().getRequest();
return servletRequest.getRequestURI();
}
}
При каждом срабатывании проверяется соответствие текущего URL переменной #{applicationScope.currentURL}. Если страница отличается, находится в "стоп-листе" и данные грязные, тогда откатываем транзакцию. Стоп-лист введен во избежание непредвиденных потерь транзакции при единой фиксации нескольких страниц (такое может быть в приложении).Код 9 - id фазы инициализаци Restore View. Интересно проследить жизненный цикл страницы-источника (откуда переходим) после изменения данных:
В целевой странице (куда переходим) грязные данные присутствуют во всем цикле:
14.01.2016
Переменные PL/SQL пакета: неочевидность
2 часа просидел над отладкой простейшего кода, не замечая подводного камня.
Допустим:
Итого: имена переменных пакета лучше начинать с префикса, либо использовать явное указание принадлежности переменной пакету.
Допустим:
create or replace package VARTEST is BANNER varchar2(255); procedure test (p_cur out sys_refcursor); end VARTEST; create or replace package body VARTEST is procedure test (p_cur out sys_refcursor) is begin open p_cur for select count(*) from v$version v where v.BANNER = BANNER; end test; end VARTEST;Вызовем-ка функцию
begin VARTEST.BANNER := 'some awsome text'; vartest.test(p_cur => :p_cur); end; -------------- count(*) 5Результат казался неожиданным, пока (случайно!) не выполнил запрос
select * from v$version v where v.BANNER = BANNER;Запрос, на удивление, выполнился и честно вернул всё содержимое вьюхи. Т.е. BANNER - это в данном случае имя поля, а не переменная пакета.
Итого: имена переменных пакета лучше начинать с префикса, либо использовать явное указание принадлежности переменной пакету.
27.10.2015
PL/SQL: MODEL (пример)
У движка отчетов JasperReports есть особенность: область детализации строго горизонтальна и занимает всю ширину страницы. Если нужно напечатать несколько маленьких бланков, которые умещаются по 2 штуки в ряд, то придется печатать всё-таки по одному.
Выход - подать на вход выборку, уже разбитую на 2 колонки.
Для простейших случаев наподобие представленного можно использовать MODEL - мощную инструкцию PL/SQL, позволяющую с выборкой производить операции с нетривиальной логикой. Применяется крайне редко в особо тяжелых случаях.
В приведенном примере сначала мы разбиваем выборку по колонкам в зависимости от четности/нечетности порядкового номера, затем на уровне выше с помощью функции LEAD склеиваем строки, чтобы убрать шахматный порядок в данных. Наконец, ограничением where id1 != 0 отсекаем пустые строки, образовавшиеся после склейки.select * from (select id1, name1, lead(id2, 1) over(order by null) id2, lead(name2, 1) over(order by null) name2 from (select id1, name1, id2, name2 from (select 1 r, 10 id, 'a' name from dual union select 2 r, 15 id, 'b' name from dual union select 3 r, 20 id, 'c' name from dual union select 4 r, 25 id, 'd' name from dual union select 5 r, 30 id, 'e' name from dual) model dimension by(r, id, name) measures(0 id1, cast(null as varchar2(255)) name1, 0 id2, cast(null as varchar2(255)) name2) rules(id1 [ mod(r, 2) != 0, id, name ] = cv(id), id2 [ mod(r, 2) = 0, id, name ] = cv(id), name1 [ mod(r, 2) != 0, id, name ] = cv(name), name2 [ mod(r, 2) = 0, id, name ] = cv(name)))) where id1 != 0
23.10.2015
PL/SQL: Месяцы в родительном падеже
Не хотелось плодить кучу условий и использовать какие-либо кириллические константы, поэтому вот:
function month_rodp(p_date in date) return varchar2 is mon varchar2(20); begin mon := trim(lower(to_char(p_date, 'MONTH'))); if (to_char(p_date, 'MM')) in (3,8) then mon := mon || chr(1072 using NCHAR_CS); else mon := substr(mon, 1, length(mon)-1) || chr(1103 using NCHAR_CS); end if; return mon; end month_rodp;
28.08.2015
Weblogic: weblogic.jdbc.wrapper.Blob_oracle_sql_BLOB cannot be cast to oracle.sql.BLOB
Ошибка возникает потому, что типы oracle.sql сервер Weblogic обвязывает в свои из weblogic.jdbc.wrapper.
Решение 1 - отключить обвязку на уровне источника данных через консоль, галочку нужно снять:
Решение 2 (и предпочтительное) - выполнить приведение типов в коде.
Код до:
Решение 1 - отключить обвязку на уровне источника данных через консоль, галочку нужно снять:
Решение 2 (и предпочтительное) - выполнить приведение типов в коде.
Код до:
public Connection getServerConnection() {
System.out.println("DataSource = " + this._ds);
Connection conn = null;
try {
if (this.conn == null){
conn = this._ds.getConnection(); //меняем эту строку
}
} catch (SQLException var4) {
String msg = "ERROR. Cannot get connection from datasource: " + var4.getMessage();
System.out.println(msg);
var4.printStackTrace();
}
return conn;
}
Код после:import oracle.jdbc.OracleConnection;
import weblogic.jdbc.extensions.WLConnection;
public Connection getServerConnection() {
System.out.println("DataSource = " + this._ds);
Connection conn = null;
try {
if (this.conn == null){
conn = (((WLConnection) this._ds.getConnection()).getVendorConnection());
}
} catch (SQLException var4) {
String msg = "ERROR. Cannot get connection from datasource: " + var4.getMessage();
System.out.println(msg);
var4.printStackTrace();
}
return conn;
}
Класс WLConnection можно подключить через com.bea.core.datasource_1.9.0.0.jar27.08.2015
Парсер SAX
SAX - альтернатива стандартному парсеру DOM, который в силу особенностей реализации (создание в памяти объекта XMLDocument, содержащего целиком весь файл), подходит только для распарсивания маленьких xml-документов.
Фишка парсера в том, что поток InputStream обрабатывается последовательно и к тем или иным событиям применяется пользовательская логика:
Фишка парсера в том, что поток InputStream обрабатывается последовательно и к тем или иным событиям применяется пользовательская логика:
SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser; parser = factory.newSAXParser(); MySAXParser prsHandler = new MySAXParser(); parser.parse(is, prsHandler);, где is - объект класса InputStream, MySAXParser - класс с перекрытыми методами обработки событий
public class MySAXParser extends DefaultHandler{
private String currentParameterTypes;
private String currentQName;
@Override
public void startDocument(){ //событие начала парсинга
System.out.println("start parse document;");
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes){
// встретили элемент
this.currentParameterTypes = qName;
}
@Override
public void endElement(String uri, String localName, String qName){
// вышли из элемента
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
// получает значение тега/атрибута this.currentParameterTypes
String value = new String(ch, start, length);
}
}
Ниже - график заполнения heap'a во время распарсивания файда в 150МБ.11.08.2015
Weblogic: Cannot read from policy store
Cannot read from policy store. Reason is PolicyStore Error, javax.xml.stream.XMLStreamException
Данная ошибка означает, что процесс не может прочитать настройки политик для домена.
При детальном осмотре файловой системы оказалось, что файл %domain%\config\fmwconfig\system-jazn-data.xml в какой-то момент стал пустым (подробнее о структуре файла). Проблема решилась заменой данного файла работоспособным, взятым у коллеги.
Данная ошибка означает, что процесс не может прочитать настройки политик для домена.
При детальном осмотре файловой системы оказалось, что файл %domain%\config\fmwconfig\system-jazn-data.xml в какой-то момент стал пустым (подробнее о структуре файла). Проблема решилась заменой данного файла работоспособным, взятым у коллеги.
17.12.2014
--------------------OeBS is over
Очень интересный проект по внедрению Oracle E-Business Suite R12, на котором я трудился 938 дней, подошел к концу. Ухожу поддерживать отечественного производителя.
Для истории:
Для истории:
08.11.2014
Создание оконного Java-приложения
Цель: создать простейшее оконное приложение на Java, выводить текст, переданный в качестве параметра.
