Thursday, December 1, 2016

Connection to SVN on Win 10 machine with DirectAccess

 There are 2 svn connectors:
  1. SVN Kit
  2. JavaHL Native
Tortoise and Eclipse plugins for SVN by default use JavaHL and that does not work over DA by default!
Direct Access goes over IPv6.
Subclise for Eclipse can be set to use SVN Kit or JavaHL as client.
By default SVN Kit goes over IPv6 but tortoise is using JavaHL and those two are incompatible. Errors like

revert C:/projects/internal/backoffice-sso
    svn: E200030: Index not exists: I_NODES_MOVED
    Index not exists: I_NODES_MOVED
  
or
  
An internal error occurred during: "Refresh SVN status cache".
Can't overwrite cause with org.tmatesoft.svn.core.SVNException: 
svn: E155010: The node 'zzz_project' was not found.

Tortoise SVN

Get version that supports IPv6.
Latest version, 1.9.5 does not have ipv6 version and does not work!

Eclipse

Download and install SlikSVN (https://sliksvn.com/download/)
Install Subclipse in Eclipse via update site, I have used version 4.2.x where update site is https://dl.bintray.com/subclipse/releases/subclipse/4.2.x/
After, verify SVN interface that is in use (Preferences - type SVN) is SilkSvn.
Subclipse 1.10.13 does not use SlikSVN as connector! I guess versions are incompatible: Subclipse uses JavaHL 1.9.3 and installed SlikSvn uses 1.9.4

Resources

Wednesday, October 5, 2016

SSO using SAML

Single Sign On using Security Assertion Markup Language

Few options

Identity Provider (IDP) is used for authentication purposes only. It is replacing login screen :)
Service Provider (SP, application) will do authorization by reading roles from LDAP/database...
or
IDP will be used for authentication and authorization.
Problem with this approach is that SP does not know when role changes.

Session information can be stored using cookies on SP and IDP domain, so IDP can verify if user user is already logged on another SP.

Flow:

  1. User comes to SP (User is not logged. SP and IDP does not have any information about user)
  2. There is no session on SP for this user and user is redirected to IDP
  3. IDP authenticate user and send SAML response to SP
  4. SP validates SAML response and reads roles from datasource and the session is established
  5. User comes to SP2 (another application)
  6. SP2 does not have a session and asks IDP about this user.
  7. IDP knows this user has session so user is not provided with login screen. IDP reads data from datasource and returns SAML response to SP2
  8. SP2 validates SAML response and reads roles from LDAP
  9. User has seamlessly logged to SP2
Handle roles and password changes on SP.

IDP notes

IdP only reads, never having any sort of admin access. This helps security ­wise, knowing that authentication system can't write or retrieve sensitive information.

Common problems

Problem

DEBUG (SAMLProcessingFilter.java:99) - Incoming SAML message is invalid
org.opensaml.ws.security.SecurityPolicyException: Validation of protocol message signature failed

Solution

Verify that SP and IDP have proper metadata.

Problem

14:54:00.798 [http-nio-8082-exec-6] DEBUG (SAMLProcessingFilter.java:99) - Incoming SAML message is invalid
org.opensaml.ws.security.SecurityPolicyException: Validation of protocol message signature failed
at org.opensaml.common.binding.security.SAMLProtocolMessageXMLSignatureSecurityPolicyRule.doEvaluate(SAMLProtocolMessageXMLSignatureSecurityPolicyRule.java:138)
at org.opensaml.common.binding.security.SAMLProtocolMessageXMLSignatureSecurityPolicyRule.evaluate(SAMLProtocolMessageXMLSignatureSecurityPolicyRule.java:107)
at org.opensaml.ws.security.provider.BasicSecurityPolicy.evaluate(BasicSecurityPolicy.java:51)
at org.opensaml.ws.message.decoder.BaseMessageDecoder.processSecurityPolicy(BaseMessageDecoder.java:132)
at org.opensaml.ws.message.decoder.BaseMessageDecoder.decode(BaseMessageDecoder.java:83)
at org.opensaml.saml2.binding.decoding.BaseSAML2MessageDecoder.decode(BaseSAML2MessageDecoder.java:70)
at org.springframework.security.saml.processor.SAMLProcessorImpl.retrieveMessage(SAMLProcessorImpl.java:105)

Solution

Add IDP public key for signing messages to java key store. It can be found in incoming saml message from IDP.

http://stackoverflow.com/questions/23059203/http-status-401-authentication-failed-incoming-saml-message-is-invalid-with

Problem

InResponseToField of the Response doesn't correspond to sent message

Log
2016-10-26 12:33:20,159 DEBUG PROTOCOL_MESSAGE,http-nio-8080-exec-4:74 -
<?xml version="1.0" encoding="UTF-8"?>
<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="http://mercurybi-local:8080/mercurybi/saml/SSO" Destination="https://authstack/saml2.0/sso" ForceAuthn="false" ID="a293907a4b8ed0d21iggb0ci9dc0bbb" IsPassive="false" IssueInstant="2016-10-26T10:33:20.100Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0">
   <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">SAMARA_SP</saml2:Issuer>
</saml2p:AuthnRequest>

2016-10-26 12:33:22,427 DEBUG PROTOCOL_MESSAGE,http-nio-8080-exec-5:113 -
<?xml version="1.0" encoding="UTF-8"?><samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Consent="urn:oasis:names:tc:SAML:2.0:consent:unspecified" Destination="http://mercurybi-local:8080/mercurybi/saml/SSO" ID="_4981b4a45c61a289809108b15d7c401bb2c0bcdae5" InResponseTo="a293907a4b8ed0d21iggb0ci9dc0bbb" IssueInstant="2016-10-26T10:33:20Z" Version="2.0">
   <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">https://authstack</saml:Issuer>
   <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
  <ds:SignedInfo>

  2016-10-26 12:33:22,698 DEBUG HttpSessionStorage,http-nio-8080-exec-5:117 - Message a293907a4b8ed0d21iggb0ci9dc0bbb not found in session A9C98F53D692EDFA486D96FB3D9F67C6
2016-10-26 12:33:22,702 DEBUG SAMLAuthenticationProvider,http-nio-8080-exec-5:98 - Error validating SAML message
org.opensaml.common.SAMLException: InResponseToField of the Response doesn't correspond to sent message a293907a4b8ed0d21iggb0ci9dc0bbb

Solution

<bean id="contextProvider" class="org.springframework.security.saml.context.SAMLContextProviderImpl">
  <property name="storageFactory">
    <bean class="org.springframework.security.saml.storage.EmptyStorageFactory"/>
  </property>
</bean>

Problem and Solution

Application is hosted on 2 different machines using different domains.
IDP manages to return proper domain name based on following rules

  1. read where to return in SP metadata
  2. if AssertionConsumerServiceURL field is present in SAML request use that one


<?xml version="1.0" encoding="UTF-8"?>

<saml2p:AuthnRequest
    AssertionConsumerServiceURL="http://app.samara.hr:8080/app/saml/SSO"
    Destination="https://myIDP/saml2.0/sso" ForceAuthn="false"
    ID="a4bi2g9cj906hj4429i0b0413h5aji4" IsPassive="false"
    IssueInstant="2016-11-03T13:57:40.212Z"
    ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
    Version="2.0" xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
    <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">SAMARA-SP</saml2:Issuer>
</saml2p:AuthnRequest>

Logout and SingleLogout feature

What will be URL used for redirects (if that option is used) update SP metadata:

<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://mydomain.samara.hr/myApp/saml/SingleLogout"/>

Send SAML request via POST

To be sure POST is used:

@Bean
public WebSSOProfileOptions defaultWebSSOProfileOptions() {
final WebSSOProfileOptions webSSOProfileOptions = new WebSSOProfileOptions();
webSSOProfileOptions.setIncludeScoping(false);
webSSOProfileOptions.setBinding(SAMLConstants.SAML2_POST_BINDING_URI);
return webSSOProfileOptions;
}

Ref:

SWITCH - Demo
okta - SAML
SAML Security Cheat Sheet
Spring Security SAML
Spring SAML - Troubleshooting common problems
Can one SP metadata file be used for 5 separate SPs running the same application

Wednesday, August 17, 2016

Gradle

generate dependency tree

$ ./gradlew dependencies > dep.txt


generate dependency tree and refresh dependencies

$ ./gradlew dependencies > dep.txt --refresh-dependencies
The --refresh-dependencies option tells Gradle to ignore all cached entries for resolved modules and artifacts.

Ref: Listing project dependencies

create java project

$ gradle init --type java-application
More info at Build Init Plugin
Clean build.gradle file

eclipse - download sources and javadoc

apply plugin: 'java'
apply plugin: 'eclipse'

eclipse {
    classpath {
        downloadJavadoc = true
        downloadSources = true
    }
}

repositories {
    mavenCentral()
    mavenLocal()
}

$ gradle cleanEclipse eclipse

If mavenLocal() is present in your repositories, don't forget to put it at the bottom of the list.


add test sources from one project to second in multiproject environment

testCompile project(':sub-project').sourceSets.test.output

publish to local repository

$ ./gradlew publishToMavenLocal

Ref

https://stackoverflow.com/questions/28404149/how-to-download-javadocs-and-sources-for-jar-using-gradle-2-0

Tuesday, August 9, 2016

Angular.JS notes

Notes

AngularJS is a JavaScript framework. It can be added to an HTML page with a <script> tag.
AngularJS extends HTML attributes with Directives, and binds data to HTML with Expressions.




A Directive is a marker on a HTML tag that tells Angular to run or reference some JavaScript code.
Controllers are where we define our app’s behavior by defining functions and values.
Modules – where our application components live
Expressions – how values get displayed within the page

AngularJS Example

index.html
<!DOCTYPE html>
<html ng-app="gemStore">
  <head>
    <script type="text/javascript" src="angular.min.js"></script>
    <script type="text/javascript" src="app.js"></script>
  </head>
  
<body ng-controller="StoreController as store">
<div ng-repeat="product in store.products">
<h1>{{product.name}}</h1>
<h2> ${{product.price}}</h2>
<p> {{product.description}}</p>
<button ng-show="product.canPurchase">Add to Cart</button>
</div>
</body>
</html>

app.js
(function() {
var app = angular.module('gemStore', []);

app.controller('StoreController', function() {
// store data in the controller
this.products = gems;
});

var gems = [
{ name: 'Azurite', price: 2.95, description: 'Dobar za prodaju....', canPurchase : true },
{ name: 'Bloodstone', price: 5.95, description: 'Ne mozes kupiti', canPurchase : false },
{ name: 'Zircon', price: 3.95, description: 'ZZZZZZ', canPurchase : true }
];

})();

Ref


Wednesday, May 25, 2016

Tomcat notes

Configure tomcat to expose files from disk

In tomcat conf/server.xml add at the bottom before </Host>:

 <Context path="/results"
                 docBase="/opt/prov/rdisk/manufacturer_results"
                 debug ="99"
                 reloadable="true">
 </Context>


In you application properties you can define:

#where to save files
path_file=/opt/prov/rdisk/manufacturer_results/{0}_name.csv
#url to fetch file
url_file=http://machine:8080/results/{0}_error.csv

Tomcat exposes files found on those places on disk.
You can reach them via http.

Thursday, April 7, 2016

Quartz with Spring - Java configuration

In my previous post Quartz with Spring and embedded database I have used xml to configure spring 3 with quartz 1.8.

Now I will configure spring 4.2 with quartz 2.2.2 using Java configuration. I am using quartz in cluster.

Java configuration class

@Configuration
@ComponentScan({ "hr.samara.job" })
public class QuartzConfig
{

@Autowired
private DataSource dataSource;
@Autowired
private JpaTransactionManager transactionManager;
@Autowired
private Environment env;

@Autowired
private SimOperation simOperation;

@Bean
public SchedulerFactoryBean scheduler()
{
SchedulerFactoryBean scheduler = new SchedulerFactoryBean();
scheduler.setConfigLocation(new ClassPathResource("quartz.properties"));

scheduler.setDataSource(dataSource);
scheduler.setTransactionManager(transactionManager);

// inject simOperation - spring bean in job
Map<String, Object> map = new HashMap<>();
map.put("simOperation", simOperation);
scheduler.setSchedulerContextAsMap(map);


scheduler.setTriggers(blockSimTrigger().getObject());
return scheduler;
}

@Bean
public CronTriggerFactoryBean blockSimTrigger()
{
CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean();
cronTriggerFactoryBean.setJobDetail(blockSimJob().getObject());
cronTriggerFactoryBean.setCronExpression(env.getProperty("job.blockSim.cron"));
cronTriggerFactoryBean.setMisfireInstructionName("MISFIRE_INSTRUCTION_FIRE_ONCE_NOW");
return cronTriggerFactoryBean;
}

@Bean
public JobDetailFactoryBean blockSimJob()
{
JobDetailFactoryBean jobDetailFactory = new JobDetailFactoryBean();
jobDetailFactory.setJobClass(BlockSimJob.class);
jobDetailFactory.setDescription("call sim block");
return jobDetailFactory;
}

}


Job class

@DisallowConcurrentExecution
public class BlockSimJob extends QuartzJobBean
{

private transient SimOperation simOperation;

@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException
{
simOperation.blockSim();
}

public void setSimOperation(SimOperation simOperation)
{
this.simOperation = simOperation;
}

}


Ref:
http://www.baeldung.com/spring-quartz-schedule

Tuesday, November 10, 2015

Web services FAQ

Using cxf 2.7, generated wsdl contains 2 files, because interface and implementation are not in same package.
Solution annotate implementation and override targetNamespace
@WebService(targetNamespace = "om.samara.hr")



Friday, August 28, 2015

Wednesday, July 29, 2015

Quartz troubleshooting

Problem:
Quartz in clustered mode, nodes are sync via db.
There are many lines like these in logs:
[2015-07-04 00:00:01,620]  WARN [QuartzScheduler_scheduler-prov011435933239135_ClusterManager] (JobStoreSupport.java:3298) - This scheduler instance (prov011435933239135) is still active but was recovered by another instance in the cluster.  This may cause inconsistent behavior.

"The most probable cause of such a cluster-related error is having cluster nodes with system clock not synchronized."



Ref:
http://quartz-scheduler.org/documentation/faq

Tuesday, July 28, 2015

web service client

Server is returning soap fault with http status 400

SOAP UI is displaying nicely













When using cxf Java client I get strange, misleading message:
org.apache.cxf.interceptor.Fault: Could not send Message.

On server side I see everything is as expected soap fault is returned with bad request status code 400.
After little debugging I found this in org.apache.cxf.transport.http.HTTPConduit class:
// "org.apache.cxf.transport.process_fault_on_http_400" property should be set in case a 
// soap fault because of a HTTP 400 should be returned back to the client (SOAP 1.2 spec)

So before making a call configure client:
Client client = ClientProxy.getClient(port);
client.getBus().setProperty("org.apache.cxf.transport.process_fault_on_http_400", true);

After that I get expected exception:
Caused by: org.apache.cxf.binding.soap.SoapFault: some validation message


One more example of calling web service with Apache CXF - now within the same project I'm doing integration test with Spock and SpringBootTest.
HelloWorldWs is interface annotated with @WebService

def setup() {
    JaxWsProxyFactoryBean proxyFactory = new JaxWsProxyFactoryBean()
    proxyFactory.setServiceClass(HelloWorldWs)
    this.pismaUrl = "http://localhost:" + this.port + "/services/pisma"
    proxyFactory.setAddress(pismaUrl)
    this.client = (HelloWorldWs) proxyFactory.create()

    Client client = ClientProxy.getClient(this.client);
    client.getBus().setProperty("org.apache.cxf.transport.process_fault_on_http_400", true);
}


web service client example


//web service interface to be called
@WebService(targetNamespace = "http://services.crm.ticketing.samara.com", name = "ticketingServicePortTypes")
@XmlSeeAlso({ObjectFactory.class})
public interface TicketingServicePortTypes {

// web service client that was generated with wsdltojava
// This class was generated by Apache CXF 3.0.3
TicketingService extends javax.xml.ws.Service

Java client that calls TicketingService, using basic authentication with u/p.
final TicketingService service = new TicketingService(); // should be singleton
final TicketingServicePortTypes port = service.getTicketingServicePort();
javax.xml.ws.BindingProvider bp = (BindingProvider) port;
log.trace("username: " + username + ", password: " + password);
bp.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, username);
bp.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, password);
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://10.105.100.127:8445/");


Using spring cxf xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task" xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:soap="http://cxf.apache.org/bindings/soap" xmlns:cxf="http://cxf.apache.org/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
        http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
        http://cxf.apache.org/bindings/soap http://cxf.apache.org/schemas/configuration/soap.xsd
        ">




<!-- jaxws client to front end -->
<jaxws:client id="crmService"
serviceClass="com.samara.generated.crm.api.TicketingServicePortTypes"
address="${crm.url}" username="${crm.username}" password="${crm.password}">
<jaxws:binding>
<soap:soapBinding mtomEnabled="false" version="1.1" />
</jaxws:binding>
</jaxws:client>

</beans>



Monday, July 27, 2015

Generating random integers in a range


Random rand;
int randomNum = rand.nextInt((max - min) + 1) + min;

or

int randomNum = ThreadLocalRandom.current().nextInt(min, max + 1);


Ref:
stackoverflow - Generating random integers in a range with Java
Random - nextInt

Monday, July 20, 2015

Disjuction (OR operator)

Writing OR clause using criteria API.

In this case operation parameter can be passed as optional / varargs (arbitrary number of values ).

private void addOperationToCriteria(Criteria criteria, SomeOperation ... operation)
{
if (operation == null)
return;
if (operation.length == 1)
criteria.add(Restrictions.eq("operation", operation[0]));
else
{
Disjunction dis = Restrictions.disjunction(); // OR
for (SomeOperation o : operation)
{
dis.add(Restrictions.eq("operation", o));
}
criteria.add(dis);
}
}


Friday, July 17, 2015

Quartz with Spring and embedded database

I'm was testing quartz at localhost with H2 embedded database.
In this case I need quartz tables prepared.

In spring config define database and wha script to load:
<jdbc:embedded-database id="dataSource" type="H2">
<jdbc:script location="classpath:recycle/quartz-h2.sql" />
</jdbc:embedded-database>


Example of spring 3.2 integration with quart 1.8:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns      = "http://www.springframework.org/schema/beans"
       xmlns:xsi  = "http://www.w3.org/2001/XMLSchema-instance"
       xmlns:task = "http://www.springframework.org/schema/task"

       xsi:schemaLocation = "http://www.springframework.org/schema/beans
                             http://www.springframework.org/schema/beans/spring-beans.xsd
                             http://www.springframework.org/schema/task
                             http://www.springframework.org/schema/task/spring-task.xsd">
                           
<!-- Setting pool to 10 threads -->
    <task:scheduler id="taskScheduler" pool-size="10"/>

    <!-- Scheduler -->
    <bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="configLocation" value="recycle/quartz.properties"/>
        <property name="dataSource" ref="dataSource"/>
        <property name="transactionManager" ref="transactionManager" />
        <property name="triggers">
        <list>
                <ref bean="txRecycleTrigger" />
            </list>
        </property>
        <!-- Fill the schedulerFactoryBeans scheduleContextMap with ALL spring
beans that shall be available for the Job implementations. The SpringBeanJobFactory will inject these beans into newly instantiated workers if they have a setter that corresponds to the beans key. This makes spring beans available even for (persisted and) deserialized Jobs. NOTE: This mechanism isn't supported by Spring 3.0 for the latest Quartz version 2.0.1 but for the previous version 1.8.5 -->
<property name="schedulerContextAsMap">
<map>
<entry key="recycleSimService" value-ref="RecycleSimService" />
<entry key="logEnabled" value="${job.logEnabled}" />
</map>
</property>
    </bean>
 
    <!-- Property ""MISFIRE_INSTRUCTION_FIRE_ONCE_NOW" means that The job is executed immediately after the scheduler discovers misfire situation.  -->
 
    <bean id="txRecycleTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="jobDetail"      ref  ="recycleSimJob" />
        <property name="cronExpression" value="${job.recycleScheduler.cronExpression}" />
        <property name="misfireInstructionName" value="MISFIRE_INSTRUCTION_FIRE_ONCE_NOW" />
    </bean>
    <bean id="recycleSimJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
      <property name="jobClass" value="com.samara.job.RecycleSimJob" />
    </bean>
 
</beans>



Job implementation

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.StatefulJob;
import org.springframework.scheduling.quartz.QuartzJobBean;

public class RecycleSimJob extends QuartzJobBean implements StatefulJob
{
 private transient static final Logger log = LoggerFactory.getLogger(RecycleSimJob.class);

 private transient RecycleSimService recycleSimService;

 @Override
 protected void executeInternal(JobExecutionContext context) throws JobExecutionException
 {
  if (getRecycleSimService() == null)
  {
   log.warn("recycleSimService is not set!");
   return;
  }
  getRecycleSimService().recycleSims(new Date());
 }

 public RecycleSimService getRecycleSimService()
 {
  return recycleSimService;
 }

 public void setRecycleSimService(RecycleSimService recycleSimService)
 {
  this.recycleSimService = recycleSimService;
 }

}

Schedule job in real time

I'm using injected org.springframework.scheduling.quartz.SchedulerFactoryBean.

JobDetail jobDetail = new JobDetail("deactivation_" + orderId, DeactivateOrderJob.class);
Map<String, Long> params = new HashMap<String, Long>();
params.put("orderId", orderId);
jobDetail.setJobDataMap(new JobDataMap(params));
final SimpleTrigger simpleTrigger = new SimpleTrigger("deactivationTrigger_" + orderId, expiryTime);
schedulerFactory.getScheduler().scheduleJob(jobDetail, simpleTrigger);

DeactivateOrderJob will be waken and it will read orderId from map.

@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException
{
     Map params = context.getJobDetail().getJobDataMap();
     Long orderId = (Long) params.get("orderId");
     .....
}

Thursday, April 23, 2015

Moving project to git repository

I have git repo at bitbucket


  1. create repository on bitbucket via web UI
  2. go to project directory folder on your machine
  3. git init
  4. git remote add origin "URL to repo"
  5. eclipse (with egit plugin) - share project using git
  6. commit & push

Ref:

Tuesday, April 7, 2015

SELECT FOR UPDATE

We have 2 machines with active active configuration and there is table with column for counters.
Db is on 3rd machine.
How to update these columns?


Example from code:

public InitialStateEntity findByIdWithLock(Long id)
{
DetachedCriteria criteria = DetachedCriteria.forClass(InitialStateEntity.class);
criteria.add(Restrictions.idEq(id));
criteria.setLockMode(LockMode.PESSIMISTIC_WRITE);
return (InitialStateEntity) criteria.getExecutableCriteria(getSession()).uniqueResult();
}



Ref:
https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/transactions.html

Monday, March 23, 2015

Download file

Implemented using Spring MVC, rest service.

Display file on screen or download as attachment.

@Controller
public class FileController
{
private static final Logger log = LoggerFactory.getLogger(FileController.class);

@RequestMapping(value = "/file/{id}", method = RequestMethod.GET)
public void getFileViaAttachment(@PathVariable String id, HttpServletResponse response)
{
log.info("getFile " + id);
try
{

String content = "testing file download";
String fileName = "mojFileIzStringa.txt";
InputStream in = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));

IOUtils.copy(in, response.getOutputStream());

response.setContentType("application/text");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
response.flushBuffer();
}
catch (IOException e)
{
e.printStackTrace();
}
}

@RequestMapping(value = "/many", method = RequestMethod.GET)
public void getManyLinesViaAttachment(HttpServletResponse response)
{
log.info("getManyLines ");
try
{
String[] linesArrays = { "prva linija", "druga linija", "xxx linija" };
List<String> linesList = Arrays.asList(linesArrays);
String fileName = "mojFileSpunoLinija.csv";
IOUtils.writeLines(linesList, null, response.getOutputStream(), StandardCharsets.UTF_8);

response.setContentType("application/text");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
response.flushBuffer();
}
catch (IOException e)
{
e.printStackTrace();
}
}

// every line in new row
@RequestMapping(value = "/getFileAsItIs", method = RequestMethod.GET, produces = "text/plain")
@ResponseBody
public String getFileAsItIs()
{
log.info("getFileAsItIs ");
String[] linesArrays = { "prva linija", "druga linija", "xxx linija" };
List<String> linesList = Arrays.asList(linesArrays);
StringBuilder sb = new StringBuilder();

for (String s : linesList)
{
sb.append(s).append(System.lineSeparator());
}

return sb.toString();
}
}

Change constraint

Table simmapping has foreign key to msisdn on 2 columns msisdn and providerId.
Change key so you can do update on providerId
Database: postgres.

ALTER TABLE public.simmapping
DROP CONSTRAINT fk_simmapping_msisdn,
ADD CONSTRAINT fk_simmapping_msisdn
   FOREIGN KEY (msisdn, msisdn_providerid)
   REFERENCES msisdn(msisdn, providerid)
   ON UPDATE CASCADE;

Tuesday, March 3, 2015

JPA Composite Key

Create class that will represent composite key and has implemented hashCode and equals methods.

public class MsisdnCompositeKey implements Serializable
{
private static final long serialVersionUID = 1L;

private String msisdn;
private Long providerId;
.....


Class that uses this composite key needs to be annotated with @IdClass and have same fields (msisdn and providedId as in example).

@Entity
@Table(name = "MSISDN")
@IdClass(value = MsisdnCompositeKey.class)
public class Msisdn
{
private static final long serialVersionUID = 1L;

@Id
private String msisdn;
@Id
private Long providerId;

.....

Ref:
https://stackoverflow.com/questions/13032948/how-to-create-and-handle-composite-primary-key-in-jpa